bzzear 2017-06-07 09:27:54 4790次浏览 1条评论 9 1 0

主要解决方法:

1)继承Yii2的yii\captcha\CaptchaAction,重写run方法进行验证码的生成、显示等操作。
2)改变getVerifyCode的参数false改为true,让每次刷新和请求都更新验证码
3)让验证码更美观,用新的字体,加上线条,背景等
有其他特殊需求可以在这些代码中自己添加即可。

控制器代码SiteController.php:

public function actions()
{
	return [
		'captcha' => [
			'class' => 'common\components\MyCaptcha',
			//'class' => 'yii\captcha\CaptchaAction',
			'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
			'maxLength' => 4, //生成的验证码最大长度
			'minLength' => 4,  //生成的验证码最短长度
			'width'=>130,
			'height'=>50,
		],
	];
}

验证码common/components/MyCaptcha.php:

<?php
namespace common\components;

use Yii;
use yii\captcha\CaptchaAction;
use yii\helpers\Url;
use yii\web\Response;

class MyCaptcha extends CaptchaAction
{
    public function init()
    {
        parent::init();
        $this->fontFile = dirname(Yii::$app->basePath) . '/source/font/elephant.ttf';
    }

    /**
     * Runs the action.
     */
    public function run()
    {
        if (Yii::$app->request->getQueryParam(self::REFRESH_GET_VAR) !== null) {
            // AJAX request for regenerating code
            $code = $this->getVerifyCode(true);
            Yii::$app->response->format = Response::FORMAT_JSON;
            return [
                'hash1' => $this->generateValidationHash($code),
                'hash2' => $this->generateValidationHash(strtolower($code)),
                // we add a random 'v' parameter so that FireFox can refresh the image
                // when src attribute of image tag is changed
                'url' => Url::to([$this->id, 'v' => uniqid()]),
            ];
        } else {
            $this->setHttpHeaders();
            Yii::$app->response->format = Response::FORMAT_RAW;
            return $this->renderImage($this->getVerifyCode(true));
        }
    }


    /**
     * Renders the CAPTCHA image based on the code using GD library.
     * @param string $code the verification code
     * @return string image contents in PNG format.
     */
    protected function renderImageByGD($code)
    {
        $image = imagecreatetruecolor($this->width, $this->height);

        $backColor = imagecolorallocate($image, mt_rand(157,255), mt_rand(157,255), mt_rand(157,255));
        imagefilledrectangle($image, 0, 0, $this->width - 1, $this->height - 1, $backColor);
        imagecolordeallocate($image, $backColor);

        if ($this->transparent) {
            imagecolortransparent($image, $backColor);
        }

        $foreColor = imagecolorallocate($image,mt_rand(0,156),mt_rand(0,156),mt_rand(0,156));

        //雪花线条
        for ($i=0;$i<6;$i++) {
            $color = imagecolorallocate($image,mt_rand(0,156),mt_rand(0,156),mt_rand(0,156));
            imageline($image,mt_rand(0,$this->width),mt_rand(0,$this->height),mt_rand(0,$this->width),mt_rand(0,$this->height),$color);
        }
        for ($i=0;$i<100;$i++) {
            $color = imagecolorallocate($image,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255));
            imagestring($image,mt_rand(1,5),mt_rand(0,$this->width),mt_rand(0,$this->height),'*',$color);
        }

        $length = strlen($code);
        $box = imagettfbbox(30, 0, $this->fontFile, $code);
        $w = $box[4] - $box[0] + $this->offset * ($length - 1);
        $h = $box[1] - $box[5];
        $scale = min(($this->width - $this->padding * 2) / $w, ($this->height - $this->padding * 2) / $h);
        $x = 10;
        $y = round($this->height * 27 / 40);
        for ($i = 0; $i < $length; ++$i) {
            $fontSize = (int) (rand(26, 32) * $scale * 0.8);
            $angle = rand(-10, 10);
            $letter = $code[$i];
            $box = imagettftext($image, $fontSize, $angle, $x, $y, $foreColor, $this->fontFile, $letter);
            $x = $box[2] + $this->offset;
        }

        imagecolordeallocate($image, $foreColor);

        ob_start();
        imagepng($image);
        imagedestroy($image);

        return ob_get_clean();
    }

}

视图中的代码:

<ul>
    <li><i class="icon-user"></i><input type="text" id="user" placeholder="请输入账号" maxlength="20" autocomplete="false"><span></span></li>
    <li><i class="icon-pwd"></i><input type="password" id="pwd" placeholder="请输入密码" maxlength="20" autocomplete="false"><span></span></li>
    <li><i class="icon-ver"></i><input type="text" id="ver" placeholder="请输入验证码" maxlength="4" autocomplete="false"><span></span>
    <?php echo Captcha::widget(['name'=>'captchaimg','captchaAction'=>'site/captcha','imageOptions'=>['class'=>'captchaimg', 'title'=>'换一个', 'alt'=>'换一个'],'template'=>'{image}']);?></li>
    <li><button id="login">登录</button></li>
</ul>

<script type="text/javascript">
	$(".captchaimg").click(function(){
		var date = new Date();
		$(this).attr('src',['site/captcha','data=',(new Date())].join('?'));
	})
<script>
觉得很赞
您需要登录后才可以评论。登录 | 立即注册