2017-02-17 21:03:26 0 评论 Yii 2.0 Boy.Lee

Yii 2.0 自定义验证码内容 Captcha DIY

{ 题记 }

换域名差不多1年,因为Google的排名回来了,所以各种五花八门的广告和评论都会来了,记得用YiiBlog.info的时候也有这样的阶段。一开始只有少量的也没当回事,但是后来就厉害了。没办法只能增加验证码的复杂程度,这次延用了老办法,使用算术验证码,一定程度上可以屏蔽一批机器人了,当然如果后面有必要,还有其他杀手锏,哈哈。

简单记录下留给有这个需求的人。

 

{ 0. 需求介绍 }

Yii 2.0框架默认显示的验证码为 FEOD 这样存字母,显然这种方式是非常非常容易被识别的。有人可能会选择增加位数,添加内容增加识别难度,这是一种方法。本例采用了另外一种方式,即显示 18-9 这种验证码。

 

{ 1. SiteController }

    public function actions()
    {
        return [

            ...

            'captcha' => [
                'class' => 'YiilibTools\eeCaptcha', //稍后解释
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
                'transparent' => true,
            ],
        ];
    }

 

{ 2. Model文件 }

class ContactMsg extends CommonBased
{
    public $verifyCode;

...

    public function rules()
    {
        return [
        
        	...
    
            [['verifyCode'], 'required'],
            ['verifyCode', 'captcha'],
        ];
    }
...

 

{ 3. View文件 }

<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?>

....

<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
    'template' => '<div class="row"><div class="col-lg-1"></div><div class="col-lg-5">{image}</div><div class="col-lg-5">{input}</div></div>',
]) ?>

<?php $form = ActiveForm::end()?>

 

{ 4. YiilibTools/eeCaptcha }

这里的逻辑也比较简单

  1. eeCaptcha extends CaptchaAction 来获得所有Yii 2.0框架关于验证码部分默认的内容
  2. 重新定义generateVerifyCode这个方法用来生成一个随机数字,这里是用的范围是10-100,注意这里生成的是答案,相关方法会把这个值写入Session和用作validate
  3. 重新定义renderImage来完成图片渲染之前的各种工作
    1. 使用随机显示颜色
    2. 设置相关样式
    3. 生成加减法公式,这里是先知道答案,之后生成公式
    4. 调用并换回夫类的renderImage 来执行默认的图片生成逻辑
<?php
namespace YiilibTools;

use yii\captcha\CaptchaAction;

class eeCaptcha extends CaptchaAction{
    
    
    protected function generateVerifyCode()
    {
        
        $code = mt_rand(10, 100);
    
        return $code;
    }
    
    
    protected function renderImage($code)
    {
        //1.rand color
        //color lib
        $colorLib[] = 0x2040A0;
        $colorLib[] = 0x2F4F4F;
        $colorLib[] = 0x483D8B;
        $colorLib[] = 0xCDBE70;
        $colorLib[] = 0xFFB90F;
        $colorLib[] = 0xEE6363;
        $colorLib[] = 0xFF1493;
        
        //get rand color for front
        $index = mt_rand(0, count($colorLib)-1);
        $this->foreColor = $colorLib[$index];
        
        //2.more style here
        $this->padding = 0;
        $this->width = 300;

        
        //3.use min or add
        $another = mt_rand(0, $code);
        if (mt_rand(0, 1)) {
            //+
            $code = $another.' + '.($code-$another);
        }else{
            //-
            $code = ($code+$another).' - '.$another;
        }
        
        return parent::renderImage($code);
    }
    
}

 

{ 5. 更多 }

比如需要使用一些逻辑性的问题,那么就可以预先准备一个数组(或数据库), 然后数组元素同时包含问题和答案。随机选择一道问题即拿到数组下标,然后将其存入session,在显示的时候通过下标找到问题,之后显示。在核对的时候也需要改成通过下标拿到答案然后将答案和用户输入进行比较。