自定义Captcha
标准的Yii验证码已经足够防护垃圾信息,但是有些情况下,你可能需要自定义验证码,例如:
- 你面对一个垃圾机器人,它可以从图片中读取文字,你需要添加更多的安全措施
- 你希望让验证码更加简单和有趣
在我们的例子中,我们将会修改Yii的验证码,它要求用户解决一个简单的算术问题,而不只是简单的重复图片中文字的内容。
准备
这个例子一开始,我们会利用添加和自定义CaptchaWidget的结果。或者也可以使用其它使用了验证码的表单,因为我们不需要修改很多已有的代码。
如何做…
我们需要自定义CaptchaAction
,它会生成验证码并将其生成图片。这个验证码应该是一个随机数字,并且图片应该是一个有相同结果的算术表达式:
- 创建
@app/components/MathCaptchaAction.php
:
<?php
namespace app\components;
use \Yii;
use yii\captcha\CaptchaAction;
class MathCaptchaAction extends CaptchaAction
{
protected function renderImage($code)
{
return parent::renderImage($this->getText($code));
}
protected function generateVerifyCode()
{
return mt_rand((int)$this->minLength,
(int)$this->maxLength);
}
protected function getText($code)
{
$code = (int) $code;
$rand = mt_rand(1, $code-1);
$op = mt_rand(0, 1);
if ($op) {
return $code - $rand . " + " . $rand;
}
else {
return $code + $rand . " - " . " " . $rand;
}
}
}
- 在我们的控制器
actions
方法中,我们需要将CaptchaAction
替换成自己的验证码动作,如下:
public function actions()
{
return [
'captcha' => [
'class' => 'app\components\MathCaptchaAction',
'minLength' => 1,
'maxLength' => 10,
],
];
}
- 运行你的表单,尝试新的验证码。它将会展示一个算术表达式,你需要输入它的答案,如下截图所示:
我们重写了两个CaptchaAction
方法,在generateVerifyCode()
中,我们生成了一个随机数而不是文本。然后我们需要渲染的是一个表达式,而不是文本,我们需要重写renderImage
。表达式是由我们自定义getText()
方法生成的。$minLength
和$maxLength
属性已经在CaptchaAction
定义了,所以我们不需要将它们加入到MathCaptchaAction
类中。
参考
欲了解更多信息,参考如下链接: