使用 mews/captcha 实现 API 验证接口
本着代码洁癖,不想安装两个验证码依赖,看了一眼 @chaijiawei 的帖子,自己研究了一下,记录下来希望能帮助到其他同学。
/*
app/Http/Controllers/Api/CaptchasController.php
*/
// 引用mews/captcha
use Mews\Captcha\Captcha;
class CaptchasController extends Controller
{
public function store(CaptchaRequest $request, Captcha $captchaBuilder)
{
// 这里与教程不同,更改了缓存前缀,便于区分
$key = 'cacheKey-'. Str::random(15);
// 创建验证码 create(生成验证码方式,是否api接口)
$captcha = $captchaBuilder->create('flat', true);
/*
创建的验证码为数组格式:
'sensitive' => $generator['sensitive'],
'key' => $generator['key'],
最终显示图片
'img' => data:image/png;base64...
key 通过hash算法用来匹配 img 显示的值,可以把 key 和 img 显示的值理解为一个键值对,后面使用 captcha_api_check() 方法来验证用户输入的验证码是否正确
*/
$phone = $request->phone;
$expiredAt = now()->addMinute(2);
Cache::put($key, [
'phone' => $phone,
// 添加验证码生成的key到缓存中
'captcha' => $captcha['key']
], $expiredAt);
$result = [
'cache_key' => $key,
'expired_at' => $expiredAt->toDateTimeString(),
// 此处与教程不同,多了一个key
'captcha_key' => $captcha['key'],
'captcha_img' => $captcha['img']
];
return response()->json($result)->setStatusCode(201);
}
}
在控制器中并没有像教程一样把生成的验证码存储到缓存中来和用户输入的验证码比较,而是把验证码生成的key
键存储到了缓存中,后面与用户输入的验证码做键值匹配,即可验证用户输入的验证码是否正确。
先来测试一下我们的返回值:
一切正常,已经得到了我们想要的值,此处和教程一样,浏览器打开图片地址,并且记录下captcha_key
的值,最好新开一个窗口来测试验证码的接口,便于填写,下面是验证码控制器部分。
/*
app/Http/Controllers/Api/VerificationCodesController.php
*/
public function store(VerificationCodeRequest $request, EasySms $easySms)
{
// 这里将教程中的 captcha_key 换成了 cache_key 不要弄错
$captchaData = Cache::get($request->cache_key);
.
.
.
// 使用captcha_api_check方法验证用户输入的验证码是否和我们缓存中记录的key相匹配,这里注意的是,判断的顺序不能错,前面的是用户输入的验证码,后面是缓存中记录的Key
if(!captcha_api_check($request->captcha_code, $captchaData['captcha']))
{
Cache::forget($request->cache_key);
throw new AuthenticationException('验证码错误');
}
}
再来验证一下验证码
接口,注意键名不要写错了。
看到验证码以通过,并生成了手机短信验证码的key
这里简单看一下captcha_api_check
方法
function captcha_api_check(string $value, string $key): bool
{
// 这里调用了mews/captcha的check_api方法
return app('captcha')->check_api($value, $key);
}
public function check_api($value, $key): bool
{
// 这里调用了 Illuminate/Hashing/BcryptHasher 的check()方法
return $this->hasher->check($value, $key);
}
我学的比较浅,才入门一个月。对laravel的框架了解还不多,源码也没怎么读过,理解的也不够深入,希望其他同学有看到的可以帮忙解答一下这里是怎么运算的。
今天又做了一遍,在验证这里遇到坑了
api_check
这个方法,需要在captcha.php
的配置文件中给bcrypt
设置为true
,否则key
无法进行解密,用哈希匹配不了用户输入的验证码