• 注册
  • 前端后端 前端后端 关注:0 内容:62

    PHP输出验证码图片(支持中文&英文验证码)

  • 查看作者
  • 打赏作者
  • 1
  • SVIP7
    帅气冲天

    问题前言

    面对复杂的网络情况,还是多给网站加条防线,来防止机器人注册垃圾评论等等。。

    验证码,想必大家并不陌生吧,这是目前最常见的防御,所以今天给大家分享一段输出验证码的PHP代码

    我这里写的是验证码图片输出和后端验证判断,对于前端显示,我这里暂时不写了,如果有需要可以评论,我再写给大家

    解决方案

    <?php 
    /**
     * 验证码图片输出(支持中文/英文)
     */
     
    // 封装验证码类
    class Captcha{
        // 定义属性
        private $width;
        private $height;
        private $chars;    // 随机字符长度
        private $font;     // 随机字体
        private $lines;    // 干扰线数量
        private $pixels;   // 干扰点数量
        private $type;     // 字符类型(中文或英文)1为中文,其他为英文
     
        // 构造函数
        public function __construct($arr=array()){
            $this->width = isset($arr['width'])?$arr['width']:100;
            $this->height = isset($arr['height'])?$arr['height']:30;
            $this->chars = isset($arr['chars'])?$arr['chars']:4;
            $this->font = isset($arr['font'])?$arr['font']:5;
            $this->lines = isset($arr['lines'])?$arr['lines']:2;
            $this->pixels = isset($arr['pixels'])?$arr['pixels']:100;
            $this->type = isset($arr['type'])?$arr['type']:1;
     
            if($this->type==1){
                $this->ChaineseCaptcha();
            }else{
                $this->generate();
            }
     
        }
     
        // 生成画布以及干扰元素
        public function makeBaseImage(){
            // 基本画布
            $image = imagecreatetruecolor($this->width, $this->height);
            // 画布颜色,随机获取
            $color = imagecolorallocate($image, mt_rand(200,255), mt_rand(200,255), mt_rand(200,255));
            // 画布填充
            imagefill($image, 0, 0, $color);
            // 调用干扰线(点) 生成函数
            // 生成干扰元素
            $this->setLines($image);  // 干扰线
            $this->setPixel($image);  // 干扰点
            // 返回画布,供其他元素部分使用
            return $image;
        }
     
        /**
         * 生成中文验证码
         * @param  string   $ttfname   使用的中文字体
         * @param  recoure  $image     图片资源
         * @param  return   中文验证码
    	 * 我这里使用的是 simkai.ttf 字体,这个可以根据需求任意更换
         */
        public function ChaineseCaptcha($ttfname='./simkai.ttf'){
            // 使用makeChainese得到的字符
            // 生成画布
            $image =$this->makeBaseImage();
            // 在画布上写中文文字
            // 文字颜色
            $color = imagecolorallocate($image,mt_rand(0,100), mt_rand(0,100), mt_rand(0,100));
            // 获取要操作的中文验证码文字
            $captcha =$this->makeChainese();
            // 开启sesssion
            @session_start();
            $_SESSION['captcha'] = $captcha;
            // 画出文字
            imagettftext($image, 16, 2, 10, 22, $color, $ttfname, $captcha);
            // 显示验证码
             $this->show($image);
            // 销毁资源
            imagedestroy($image);
        }
     
        /**  该环境是在 utf-8 下使用,若是gbk,请谨慎使用
         * @param  string   $filename  保存的中文文字文件
         * @return char_chainese
         * content_chainese.txt 我罗列了一些中文字符,这个可以根据需求自己修改
         */
        private function makeChainese($filename='./content_chainese.txt'){
            $str = file_get_contents($filename);
            $captcha ='';
            for($i=0 ;$i<$this->chars;$i++){
                $rand = mt_rand(0 ,strlen($str)-1);
                $rand = $rand-($rand%3);
                $captcha .=substr($str, $rand,3);
            }
            return $captcha;
        }
     
     
        /**
     	 * 生成验证码图片的方法
         * @return 图片
         */
        public function generate(){
            // 制作画布
            $image =$this->makeBaseImage();        
            // 生成随机字符
            $captcha = $this->setRandCaptcha($image ,$this->chars);
            // session 保存
            session_start();
            $_SESSION['captcha'] = $captcha;
            // 把字符串写入图片资源
            // 颜色
            $color = imagecolorallocate($image,mt_rand(0,100),mt_rand(0,100),mt_rand(0,100));
            imagestring($image ,$this->font ,30,8,$captcha ,$color);
            $this->show($image);
            // 释放图片资源
            imagedestroy($image);
        }
     
        private function show($image){
            header("content-type:image/png");
            imagepng($image);
        }
     
        // 生成随机字符
        private function setRandCaptcha(){
            // 生成随机字符串
            // $str =implode('' ,array_merge(range('1', '9'),range('a', 'z'),range('A', "Z")));
    		// 去掉了 0 1 O l 等
            $str = "23456789ABCDEFGHJKLMNPQRSTUVYXZabcdefghkmnpqrstuvyxz";
            // 得到随机字符串
            $captcha ='';
            for($i=0 ;$i<$this->chars;$i++){
                $captcha .=$str[mt_rand(0,strlen($str)-1)].'';
            }
            return $captcha;
            
        }
     
        // 增加干扰线
        /**
         * @param  resource  $image
         */
        private function setLines($image){
            // 线的颜色
            for($i=0 ; $i<$this->lines ;$i++){
                $color = imagecolorallocate($image, mt_rand(100,150), mt_rand(100,150), mt_rand(100,150));
                imageline($image, mt_rand(0,$this->width), mt_rand(0,$this->height), mt_rand(0,$this->width), mt_rand(0,$this->height), $color);
            }
        }
     
    
        /**
    	 * 增加像素点
         * @return 返回点
         */
        private function setPixel($image){
            // 循环画点
            for($i=0;$i<$this->pixels;$i++){
                $color=imagecolorallocate($image,mt_rand(150,200), mt_rand(150,200), mt_rand(150,200));
                // 生成点
                imagesetpixel($image, mt_rand(0,$this->width), mt_rand(0,$this->height), $color);
            }
        }
     
    
        /**
    	 * 增加验证方法
         * @param  string  $captcha  用户输入的验证码
         * @return boolean
         */
        public static function compareCaptcha($captcha){
            // 比较,不区分大小写
            // 开启session
            session_start();
            return  strtolower($captcha)===strtolower($_SESSION['captcha']);
        }
     
    }
    
    // 输出验证码(type=1为中文,其他为英文)
    $c = new Captcha(array('type'=>1));

    运行后:

    PHP输出验证码图片(支持中文&英文验证码)

    使用说明

    请根据自己实际情况做相应修改


    源码下载

    隐藏内容需要回复可以看见

    回复

    楼主辛苦了,谢谢楼主,楼主好人一生平安!

    回复

    请登录之后再进行评论

    登录

    我关注的论坛

    暂没有数据

  • 发布内容
  • 做任务
  • 偏好设置
  • 直达底部
  • 帖子间隔 侧栏位置: