API接口图形验证码生成
用途
适用于登录/注册/发送短信验证码前校验等等,代码可以整合到 ThinkPHP laravel 框架
使用
方法返回一个base64加密的图形,返回到前端即可,同时会返回一个解密的验证码(这个不到带到前端,自己缓存存储起来就行)
/** * 获取图形验证码 * @return string[] */ function getCaptcha() { $imageW = 0; // 验证码位数 $length = 4; // 验证码字体大小 $fontSize = 25; $imageH = 0; $image = null; $bg = [243, 251, 254]; $color = null; $fontttf = ''; $useImgBg = false; /********* 以上是配置项 *********/ // 图片宽(px) $imageW || $imageW = $length * $fontSize * 1.5 + $length * $fontSize / 2; // 图片高(px) $imageH || $imageH = $fontSize * 2.5; // 建立一幅 $imageW x $imageH 的图像 $image = imagecreate($imageW, $imageH); // 设置背景 imagecolorallocate($image, $bg[0], $bg[1], $bg[2]); // 验证码字体随机颜色 $color = imagecolorallocate($image, mt_rand(1, 150), mt_rand(1, 150), mt_rand(1, 150)); // 验证码使用随机字体 $ttfPath = WEB_PATH . '/ttfs/'; $dir = dir($ttfPath); $ttfs = []; while (false !== ($file = $dir->read())) { if ('.' != $file[0] && substr($file, -4) == '.ttf') { $ttfs[] = $file; } } $dir->close(); $fontttf = $ttfs[array_rand($ttfs)]; $fontttf = $ttfPath . $fontttf; // 绘杂点 $codeSet = '2345678abcdefhijkmnpqrstuvwxyz'; for ($i = 0; $i < 10; $i++) { //杂点颜色 $noiseColor = imagecolorallocate($image, mt_rand(150, 225), mt_rand(150, 225), mt_rand(150, 225)); for ($j = 0; $j < 5; $j++) { // 绘杂点 imagestring($image, 5, mt_rand(-10, $imageW), mt_rand(-10, $imageH), $codeSet[mt_rand(0, 29)], $noiseColor); } } // 绘干扰线 $px = $py = 0; // 曲线前部分 $A = mt_rand(1, $imageH / 2); // 振幅 $b = mt_rand(-$imageH / 4, $imageH / 4); // Y轴方向偏移量 $f = mt_rand(-$imageH / 4, $imageH / 4); // X轴方向偏移量 $T = mt_rand($imageH, $imageW * 2); // 周期 $w = (2 * M_PI) / $T; $px1 = 0; // 曲线横坐标起始位置 $px2 = mt_rand($imageW / 2, $imageW * 0.8); // 曲线横坐标结束位置 for ($px = $px1; $px <= $px2; $px = $px + 1) { if (0 != $w) { $py = $A * sin($w * $px + $f) + $b + $imageH / 2; // y = Asin(ωx+φ) + b $i = (int)($fontSize / 5); while ($i > 0) { imagesetpixel($image, $px + $i, $py + $i, $color); // 这里(while)循环画像素点比imagettftext和imagestring用字体大小一次画出(不用这while循环)性能要好很多 $i--; } } } // 曲线后部分 $A = mt_rand(1, $imageH / 2); // 振幅 $f = mt_rand(-$imageH / 4, $imageH / 4); // X轴方向偏移量 $T = mt_rand($imageH, $imageW * 2); // 周期 $w = (2 * M_PI) / $T; $b = $py - $A * sin($w * $px + $f) - $imageH / 2; $px1 = $px2; $px2 = $imageW; for ($px = $px1; $px <= $px2; $px = $px + 1) { if (0 != $w) { $py = $A * sin($w * $px + $f) + $b + $imageH / 2; // y = Asin(ωx+φ) + b $i = (int)($fontSize / 5); while ($i > 0) { imagesetpixel($image, $px + $i, $py + $i, $color); $i--; } } } // 绘验证码 $code = []; // 验证码 $codeNX = 0; // 验证码第N个字符的左边距 for ($i = 0; $i < $length; $i++) { $code[$i] = $codeSet[mt_rand(0, strlen($codeSet) - 1)]; $codeNX += mt_rand($fontSize * 1.2, $fontSize * 1.6); imagettftext($image, $fontSize, mt_rand(-40, 40), $codeNX, $fontSize * 1.6, $color, $fontttf, $code[$i]); } // 验证码明文 $plaintext_code = ''; foreach ($code as $this_code) { $plaintext_code .= $this_code; } // 输出图像 ob_start(); imagepng($image); $content = ob_get_contents(); ob_end_clean(); imagedestroy($image); return [ 'yzm' => 'data:image/png;base64,' . base64_encode($content), 'code' => $plaintext_code ]; }
其中需要引入字体文件,这个需要更改代码部分:
$ttfPath = WEB_PATH . '/ttfs/'; // 替换为自己的路径
字体包下载:
实际返回例子
{ "yzm": "data:image/png;base64,这里会是一串经过 Base64 编码的图形验证码", "code": "a6d7" }
验证思路
将用户的 ip 作为键存到缓存中,缓存的值就是这个返回的整个数组。校验的时候直接对比缓存的 code 即可,需要注意的是一旦校验成功的话就删除缓存!
评论