使用接口api调用tp5验证码验证时一直提示失败的解决方案

大家都知道,thinkphp框架的特点就是MVC模式,验证码也是基于MVC开发的,所以验证码是Session存储的,Session存储在接口端,当我们访问了浏览器才会执行Session,所以我们通过接口调用的方式保存登录信息不行,验证码也不行。那该怎么办呢,下面来介绍下详细的解决步骤。

解决原理就是将验证码对Session改成Cache缓存,没错,就是这么干,只需要修改两个地方即可。

1)找到Captcha的源文件:vendor/topthink/think-captcha/src/Captcha.php

修改:

php 复制代码
/**
     * 验证验证码是否正确
     * @access public
     * @param string $code 用户验证码
     * @param string $id   验证码标识
     * @return bool 用户验证码是否正确
     */
    public function check($code, $id = '')
    {
        $key = $this->authcode($this->seKey) . $id;
        // 验证码不能为空
        $secode = Cache::get($key, ''); //在这里把Session换成Cache
        if (empty($code) || empty($secode)) {
            return false;
        }
        // session 过期
        if (time() - $secode['verify_time'] > $this->expire) {
            Session::delete($key, '');
            return false;
        }

        if ($this->authcode(strtoupper($code)) == $secode['verify_code']) {
            $this->reset && Session::delete($key, '');
            return true;
        }

        return false;
    }

2)在同一个文件中找到生成验证码的方法,同样将Session改成Cache

php 复制代码
/**
     * 输出验证码并把验证码的值保存的session中
     * 验证码保存到session的格式为: array('verify_code' => '验证码值', 'verify_time' => '验证码创建时间');
     * @access public
     * @param string $id 要生成验证码的标识
     * @return \think\Response
     */
    public function entry($id = '')
    {
        // 图片宽(px)
        $this->imageW || $this->imageW = $this->length * $this->fontSize * 1.5 + $this->length * $this->fontSize / 2;
        // 图片高(px)
        $this->imageH || $this->imageH = $this->fontSize * 2.5;
        // 建立一幅 $this->imageW x $this->imageH 的图像
        $this->_image = imagecreate($this->imageW, $this->imageH);
        // 设置背景
        imagecolorallocate($this->_image, $this->bg[0], $this->bg[1], $this->bg[2]);

        // 验证码字体随机颜色
        $this->_color = imagecolorallocate($this->_image, mt_rand(1, 150), mt_rand(1, 150), mt_rand(1, 150));
        // 验证码使用随机字体
        $ttfPath = __DIR__ . '/../assets/' . ($this->useZh ? 'zhttfs' : 'ttfs') . '/';

        if (empty($this->fontttf)) {
            $dir  = dir($ttfPath);
            $ttfs = [];
            while (false !== ($file = $dir->read())) {
                if ('.' != $file[0] && substr($file, -4) == '.ttf') {
                    $ttfs[] = $file;
                }
            }
            $dir->close();
            $this->fontttf = $ttfs[array_rand($ttfs)];
        }
        $this->fontttf = $ttfPath . $this->fontttf;

        if ($this->useImgBg) {
            $this->_background();
        }

        if ($this->useNoise) {
            // 绘杂点
            $this->_writeNoise();
        }
        if ($this->useCurve) {
            // 绘干扰线
            $this->_writeCurve();
        }

        // 绘验证码
        $code   = []; // 验证码
        $codeNX = 0; // 验证码第N个字符的左边距
        if ($this->useZh) {
            // 中文验证码
            for ($i = 0; $i < $this->length; $i++) {
                $code[$i] = iconv_substr($this->zhSet, floor(mt_rand(0, mb_strlen($this->zhSet, 'utf-8') - 1)), 1, 'utf-8');
                imagettftext($this->_image, $this->fontSize, mt_rand(-40, 40), $this->fontSize * ($i + 1) * 1.5, $this->fontSize + mt_rand(10, 20), $this->_color, $this->fontttf, $code[$i]);
            }
        } else {
            for ($i = 0; $i < $this->length; $i++) {
                $code[$i] = $this->codeSet[mt_rand(0, strlen($this->codeSet) - 1)];
                $codeNX += mt_rand($this->fontSize * 1.2, $this->fontSize * 1.6);
                imagettftext($this->_image, $this->fontSize, mt_rand(-40, 40), $codeNX, $this->fontSize * 1.6, $this->_color, $this->fontttf, $code[$i]);
            }
        }

        // 保存验证码
        $key                   = $this->authcode($this->seKey);
        $code                  = $this->authcode(strtoupper(implode('', $code)));
        $secode                = [];
        $secode['verify_code'] = $code; // 把校验码保存到session
        $secode['verify_time'] = time(); // 验证码创建时间
        Cache::set($key . $id, $secode, '');  //这个地方也是将Session改成Cache

        ob_start();
        // 输出图像
        imagepng($this->_image);
        $content = ob_get_clean();
        imagedestroy($this->_image);

        return response($content, 200, ['Content-Length' => strlen($content)])->contentType('image/png');
    }

具体改哪行看注释说明。

到此,问题解决。

相关推荐
JaguarJack18 小时前
FrankenPHP 原生支持 Windows 了
后端·php·服务端
BingoGo18 小时前
FrankenPHP 原生支持 Windows 了
后端·php
JaguarJack2 天前
PHP 的异步编程 该怎么选择
后端·php·服务端
BingoGo2 天前
PHP 的异步编程 该怎么选择
后端·php
JaguarJack2 天前
为什么 PHP 闭包要加 static?
后端·php·服务端
ServBay3 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954484 天前
CTF 伪协议
php
BingoGo6 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack6 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo7 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php