首页> 实战笔录 >PHP开发笔记 >ThinkPHP ThinkPHP

TP6实现前后端分离的图片验证码,验证码怎么以接口形式返回

作者:小萝卜 2024-04-17 浏览 76

简介thinkphp6.1提供的验证码插件是基于session,对于前后端分离的项目,并不能直接使用,但是我们可以间接使用它,而不用重新写一个插件。

thinkphp6.1提供的验证码插件是基于session,对于前后端分离的项目,并不能直接使用,但是我们可以间接使用它,而不用重新写一个插件。

首先我们安装一下官网提供的验证码插件

composer require topthink/think-captcha

输出验证码

接下里看看控制器写的获取验证码的代码

//图片验证码
public function verify(){
    $uniqid = uniqid(rand(00000,99999));
    $rs = Captcha::create();
    $base64_image = "data:image/png;base64," . base64_encode($rs->getData());
    $key = session('captcha.key');

    cache('loginCode_'.$uniqid,$key);
    return $this->success(['uniqid'=>$uniqid,'image'=>$base64_image]);
}

正常情况下,你只需这样return Captcha::create(),就能在网页上看到验证码,但前面说了,这是前后端分离的项目,因此返回给前端需要两个东西:用于设置缓存的唯一标识和base64加密的图片

接下来解释一下代码,为什么是这么写的

我看了一下源码,打开Captcha.php发现Captcha::create()返回的是一个Response对象

public function create(string $config = null, bool $api = false): Response

Response里面有个getData()就是获取内容的方法,因此base64_encode($rs->getData())就是获取验证码图片

另外我们从源码中的generate(),这个是生成验证码的方法,其中有这样的代码

//$key这里的$key是验证码字符
$hash = password_hash($key, PASSWORD_BCRYPT, ['cost' => 10]);
$this->session->set('captcha', [
    'key' => $hash,
]);

把验证码字符进行加密,存储到session,因此这里使用session('captcha.key')获取到这个key值,然后我们把它存储到缓存中,而这个key是使用uniqid()方法生成的唯一标识

验证输入的验证码是否正确

还是先看看验证的代码

$data = $this->request->post();
$key = cache('loginCode_'.$data['uniqid']);
if($key && password_verify(mb_strtolower($data['code'], 'UTF-8'), $key)){
    cache('loginCode_'.$data['uniqid'],null);
}else{
    return $this->failure(199,'验证码错误');
}

首先前端需要提交uniqidcode这两个字段过来,第一步判断cache('loginCode_'.$data['uniqid'])是否存在,如果存在,就判断输入进来的验证码是否正确,这里用到password_verify(),很多人可能有疑问,为什么这么写?

答案还是在源码里面,还是打开Captcha.php,其中有个验证验证码是否正确的方法

/**
  * 验证验证码是否正确
  * @access public
  * @param string $code 用户验证码
  * @return bool 用户验证码是否正确
*/
public function check(string $code): bool
{
    if (!$this->session->has('captcha')) {
        return false;
    }
    //就是这三行代码
    $key = $this->session->get('captcha.key');
    $code = mb_strtolower($code, 'UTF-8');
    $res = password_verify($code, $key);

    if ($res) {
        $this->session->delete('captcha');
    }

    return $res;
}

我们对应的修改:

//源码
$key = $this->session->get('captcha.key');

//我们的代码
$key = cache(ADMIN_LOGIN_VERIFY_.$data['uniqid']);

//源码
$code = mb_strtolower($code, 'UTF-8');
$res = password_verify($code, $key);

//我们的代码
password_verify(mb_strtolower($data['code'], 'UTF-8'), $key)

其实就是照搬过来,一个前后端分离的验证码就这么简单的实现了~

很赞哦! (0)

文章评论

    高端网站建设