mews/captcha 验证码源码分析笔记

准备使用 mews/captcha 作为注册时的图片验证码。

追了下源码,大致分几步:

  1. 启动app时,注册 captcha 验证规则。这里利用的是 注册自定义验证规则中的 Using Extensions
    vendor/mews/captcha/src/CaptchaServiceProvider.php

    public function boot()
    {
       ...
        // Validator extensions
        $this->app['validator']->extend('captcha', function($attribute, $value, $parameters)
        {
            return captcha_check($value);
        });
    
        ...
    }
  2. 加载验证码页面时,生成验证码图片,同时将验证码值加入session
    vendor/mews/captcha/src/CaptchaController.php

    public function getCaptcha(Captcha $captcha, $config = 'default')
    {
        if (ob_get_contents())
        {
            ob_clean();
        }
        return $captcha->create($config);
    }
  3. 在注册时,会创建一个validator,将刚才注册的自定义rule写入第二参数数组,第三参数为自定义的错误消息。
    app/Http/Controllers/Auth/RegisterController.php

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:6|confirmed',
            'captcha' => 'required|captcha',
        ], [
            'captcha.required' => '验证码不能为空',
            'captcha.captcha' => '请输入正确的验证码',
        ]);
    }
  4. 然后会对此validator进行validate。captcha这个rule就会将request中的captcha的值与session中的captcha值进行比较,而且是使用password_verify这个函数,避免了时序攻击。
    vendor/mews/captcha/src/Captcha.php

    public function check($value)
    {
        if ( ! $this->session->has('captcha'))
        {
            return false;
        }
    
        $key = $this->session->get('captcha.key');
        $sensitive = $this->session->get('captcha.sensitive');
    
        if ( ! $sensitive)
        {
            $value = $this->str->lower($value);
        }
    
        $this->session->remove('captcha');
    
        return $this->hasher->check($value, $key);
    }
  5. 如果出现图片验证码输入错误或者是未输入,则会跳转为上一个页面(也就是注册页面),原因是因为ValidationException是一种比较特殊的异常,不会直接抛出错误,会将异常转换为某种预定义的响应,在这个场景下,就会跳转到上一个页面并附上除了密码的input值并带上错误信息了,这也是验证失败后,可以显示错误信息的原因。
    vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php

    protected function invalid($request, ValidationException $exception)
    {
        $url = $exception->redirectTo ?? url()->previous();
    
        return redirect($url)
                ->withInput($request->except($this->dontFlash))
                ->withErrors(
                    $exception->errors(),
                    $exception->errorBag
                );
    }
本作品采用《CC 协议》,转载必须注明作者和本文链接
日拱一卒
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
93
粉丝
85
喜欢
153
收藏
121
排名:71
访问:11.4 万
私信
所有博文
社区赞助商