PHP图片验证码如何实现?更加完善的封装

以下是一个更完善的验证码类:

/**
 * 验证码生成工具类
 */
class Captcha
{
    protected $length = 4; // 验证码长度
    protected $fonts = ['arial.ttf']; // 验证码字体
    protected $width = 100; // 验证码宽度
    protected $height = 40; // 验证码高度
    protected $bg_color = [255, 255, 255]; // 背景颜色
    protected $text_color = [0, 0, 0]; // 验证码字体颜色
    protected $pixel_noise = 0; // 像素噪点密度
    protected $line_noise = 0; // 直线噪点密度

    public function __construct($options = [])
    {
        foreach ($options as $key => $value) {
            $this->$key = $value;
        }
    }

    public function generate()
    {
        // 创建画布
        $image = imagecreatetruecolor($this->width, $this->height);

        // 设定背景色
        $bg_color = imagecolorallocate($image, ...$this->bg_color);
        imagefill($image, 0, 0, $bg_color);

        // 生成验证码字符串
        $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
        $str = '';
        for ($i = 0; $i < $this->length; $i++) {
            $str .= $chars[mt_rand(0, strlen($chars) - 1)];
        }

        // 绘制验证码字符串
        $text_color = imagecolorallocate($image, ...$this->text_color);
        $char_width = $this->width / $this->length;
        $char_height = $this->height - 8;
        $font_size = $char_height * 0.75;
        foreach (str_split($str) as $i => $char) {
            $font_file = __DIR__ . '/fonts/' . $this->fonts[mt_rand(0, count($this->fonts) - 1)];
            $angle = mt_rand(-10, 10);
            $x = $char_width * $i + ($char_width - $font_size) / 2;
            $y = $char_height + $font_size / 2 - 4;
            imagettftext($image, $font_size, $angle, $x, $y, $text_color, $font_file, $char);
        }

        // 添加像素噪点
        if ($this->pixel_noise > 0) {
            for ($i = 0; $i < $this->pixel_noise; $i++) {
                $x = mt_rand(0, $this->width);
                $y = mt_rand(0, $this->height);
                $color = imagecolorallocate($image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
                imagesetpixel($image, $x, $y, $color);
            }
        }

        // 添加直线噪点
        if ($this->line_noise > 0) {
            for ($i = 0; $i < $this->line_noise; $i++) {
                $x1 = mt_rand(0, $this->width);
                $y1 = mt_rand(0, $this->height);
                $x2 = mt_rand(0, $this->width);
                $y2 = mt_rand(0, $this->height);
                $color = imagecolorallocate($image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
                imageline($image, $x1, $y1, $x2, $y2, $color);
            }
        }

        // 输出图像
        header('Content-type: image/png');
        imagepng($image);

        // 释放资源
        imagedestroy($image);

        // 把验证码字符串存储到会话中
        session_start();
        $_SESSION['captcha'] = strtolower($str);
    }

    public function validate($input)
    {
        session_start();
        $captcha = isset($_SESSION['captcha']) ? $_SESSION['captcha'] : '';
        unset($_SESSION['captcha']);
        return strtolower($input) === strtolower($captcha);
    }
}

示例使用方法:

// 实例化验证码生成器
$captcha = new Captcha([
    'length' => 4, // 验证码长度
    'width' => 120, // 验证码宽度
    'height' => 32, // 验证码高度
    'bg_color' => [240, 240, 240], // 背景颜色
    'text_color' => [20, 20, 20], // 字体颜色
    'pixel_noise' => 50, // 像素噪点密度
    'line_noise' => 5,  // 直线噪点密度
]);

// 生成验证码
$captcha->generate();

// 验证验证码
if ($captcha->validate($_POST['captcha'])) {
    echo '验证通过';
} else {
    echo '验证失败';
}

此验证码类有以下改进:

  • 可以通过构造函数传递参数,而不需要通过类属性手动配置;
  • 可以配置多个字体文件,每次绘制验证码时随机选择一个字体;
  • 可以配置像素噪点和直线噪点密度。
© 版权声明
THE END
喜欢就支持一下吧
点赞14
评论 抢沙发

请登录后发表评论

    暂无评论内容