captcha icon indicating copy to clipboard operation
captcha copied to clipboard

captcha_api_check 不安全

Open zouyan198429 opened this issue 6 years ago • 1 comments

////验证操作 if (!captcha_api_check($request->captcha, $request->key)){ return $this->response->array(['status_code' => 400, 'message' => '验证码不匹配' ]); }

https://blog.csdn.net/Eric_Alive/article/details/83274143

这种api的方式,只是能生成的验证码,进行了hash。 但是这有个问题时,在调用captcha_api_check函数后或验证后并没有让其它过期功能。这样我就可以用这个code 和key常期请求api。他也在验证通过的。因为只是对比了code的hash值.

想到的一个解决办法是,在发验证码时,把成生的hash缓存起来, 判断时:在判断captcha_api_check的同时,再验证hash缓存是否还存在(不存在说明已经使用过了,存在说明还没有使用)。 验证通过后,立即删除缓存。

zouyan198429 avatar Nov 25 '19 09:11 zouyan198429

暂时写了一个解决方案。全安性有所提高。


<?php
namespace App\Services\Captcha;
use App\Services\Tool;

class CaptchaCode
{
    public static $captcha_pre = "captcha:";// 缓存皱起前缀
    public static $captcha_expire = 60 * 3;// 过期时间 3分钟
    public static $captcha_operate = 3;// 操作 1 转为json 2 序列化 3 不转换

    /**
     * 生成验证码
     *
     * @param string $config
     * @param int $captcha_expire 过期时间
     * @return  array
     *  $captchaParams =  [
     *      "sensitive" => true,
     *      "key" => "$2y$10$4UTAMBN0hd1V6wP3bVmbhu/PQf/y9Mz6FhFJ/VtU8CkwmRkBF8/cy",// 验证码的hash值
     *      "img" => "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAAkCAYAAABCKP5eAAAA",// base64后的图片
     *  ];
     * @author zouyan([email protected])
     */
    public static function createCodeAPI(string $config = 'default', $captcha_expire = 180){
        if(!is_numeric($captcha_expire) || $captcha_expire <= 0 ) $captcha_expire = static::$captcha_expire;
        $captchaParams = app('captcha')->create($config, true);
        $captchaKey = $captchaParams['key'];
        // 缓存起来
        Tool::setRedis(static::$captcha_pre, $captchaKey, 1, $captcha_expire , static::$captcha_operate);
        return $captchaParams;
    }

    /**
     * 生成验证码
     *
     * @param string $captcha_code 验证码
     * @param string $captcha_key 缓存key
     * @param boolean $del_cache 通过验证是否删除缓存 true:删除:false:不删除
     * @param string $errDo 错误处理方式 1 throws 2直接返回错误
     * @return  mixed sting 具体错误(验证不通过) ; throws 错误 true:验证通过 ;
     * @author zouyan([email protected])
     */
    public static function captchaCheckAPI($captcha_code = '', $captcha_key = '', $del_cache = false, $errDo = 1){
        if(is_string($captcha_code) && strlen($captcha_code) <= 0){
            $errMsg = '验证码不能为空!';
            if($errDo == 1) throws($errMsg);
            return $errMsg;
        }
        if(!captcha_api_check($captcha_code, $captcha_key)) {
            $errMsg = '验证码错误!';
            if($errDo == 1) throws($errMsg);
            return $errMsg;
        }
        if(Tool::getRedis(static::$captcha_pre . $captcha_key, static::$captcha_operate) != 1){
            $errMsg = '验证码已过期,请刷新重试!!';
            if($errDo == 1) throws($errMsg);
            return $errMsg;
        }
        // 验证通过删除缓存
        if($del_cache) Tool::delRedis(static::$captcha_pre . $captcha_key);
        return true;
    }
}

zouyan198429 avatar Nov 25 '19 10:11 zouyan198429