自定义Captcha

标准的Yii验证码已经足够防护垃圾信息,但是有些情况下,你可能需要自定义验证码,例如:

  • 你面对一个垃圾机器人,它可以从图片中读取文字,你需要添加更多的安全措施
  • 你希望让验证码更加简单和有趣

在我们的例子中,我们将会修改Yii的验证码,它要求用户解决一个简单的算术问题,而不只是简单的重复图片中文字的内容。

准备

这个例子一开始,我们会利用添加和自定义CaptchaWidget的结果。或者也可以使用其它使用了验证码的表单,因为我们不需要修改很多已有的代码。

如何做…

我们需要自定义CaptchaAction,它会生成验证码并将其生成图片。这个验证码应该是一个随机数字,并且图片应该是一个有相同结果的算术表达式:

  1. 创建@app/components/MathCaptchaAction.php
  1. <?php
  2. namespace app\components;
  3. use \Yii;
  4. use yii\captcha\CaptchaAction;
  5. class MathCaptchaAction extends CaptchaAction
  6. {
  7. protected function renderImage($code)
  8. {
  9. return parent::renderImage($this->getText($code));
  10. }
  11. protected function generateVerifyCode()
  12. {
  13. return mt_rand((int)$this->minLength,
  14. (int)$this->maxLength);
  15. }
  16. protected function getText($code)
  17. {
  18. $code = (int) $code;
  19. $rand = mt_rand(1, $code-1);
  20. $op = mt_rand(0, 1);
  21. if ($op) {
  22. return $code - $rand . " + " . $rand;
  23. }
  24. else {
  25. return $code + $rand . " - " . " " . $rand;
  26. }
  27. }
  28. }
  1. 在我们的控制器actions方法中,我们需要将CaptchaAction替换成自己的验证码动作,如下:
  1. public function actions()
  2. {
  3. return [
  4. 'captcha' => [
  5. 'class' => 'app\components\MathCaptchaAction',
  6. 'minLength' => 1,
  7. 'maxLength' => 10,
  8. ],
  9. ];
  10. }
  1. 运行你的表单,尝试新的验证码。它将会展示一个算术表达式,你需要输入它的答案,如下截图所示:

自定义Captcha - 图1

我们重写了两个CaptchaAction方法,在generateVerifyCode()中,我们生成了一个随机数而不是文本。然后我们需要渲染的是一个表达式,而不是文本,我们需要重写renderImage。表达式是由我们自定义getText()方法生成的。$minLength$maxLength属性已经在CaptchaAction定义了,所以我们不需要将它们加入到MathCaptchaAction类中。

参考

欲了解更多信息,参考如下链接: