栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > PHP

特别简单的PHP验证码识别

PHP 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力
本篇文章带大家介绍超简单的PHP验证码识别。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

网站的登陆页、注册页等等等到处都是验证码,然而你的验证码真的安全么?也许只需要一段简单的小程序,你的验证码就会如同虚设。本文只是简单实现,不会太过深入。
有攻就有防

写这篇文章完全是因为同事的公众号发了一篇文章叫"实践-写个验证码",你简单写了一下,我就简单破解一下试试,生活处处有乐趣啊~

生成验证码

Copy代码,执行,生成如下验证码:


5726d767ec9b9624fb6707d8c71b76a.png

如图我们能发现,这个验证码格式特别"规范",字体大小一样,颜色都是黑色,让我们省了不少事儿。

二值化

程序读图,二值化(关键点在于查找字体颜色的阈值,这个验证码都是黑色,so...),通过程序一个像素点一个像素点判断,将属于字体颜色的标记为*,非字体颜色标记为0


57c523dfa6e8d003d42254e0f123ee2.png

从上面的图,能够大概看出验证码的样子(YTAD)

分析图像,切割

切割出字符串(先切绿线,再分别切蓝线,这样即使这个字符上下移动一下,也不太容易影响我们的切割)


c347ce726519d02e396dc195a0b951f.png

提取特征码

将字符串拆分后,我们多次获取验证码,将a-z,A-Z,0-9等验证码的特征码全部记录下来。


c90b1c6cfb1c587d10d6dbd8ae84856.png

这个是提取出来的字母Y

识别

识别的过程就是重复上面的:二值化->切割->提取特征码,再加上和之前提取的特征码比对相似度,就OK了。

PHP代码实现

class vCode{

    //字符特征码
    private $_wordKeys = array (
 'A' => '000**00000****000**00**0**0000****0000****0000************0000****0000****0000**',
 'B' => '******00**000**0**0000****000**0******00**000**0**0000****0000****000**0******00',
 'C' => '00*****00**000****00000***000000**000000**000000**000000**00000*0**000**00*****0',
 'D' => '******00**000**0**0000****0000****0000****0000****0000****0000****000**0******00',
 'E' => '*********00000**00000**00000******0**00000**00000**00000**00000*******',
 'F' => '**********000000**000000**000000******00**000000**000000**000000**000000**000000',
 'G' => '00*****00**000****000000**000000**000000**000*****0000****0000**0**000**00*****0',
 'H' => '**0000****0000****0000****0000************0000****0000****0000****0000****0000**',
 'I' => '******00**0000**0000**0000**0000**0000**0000**0000**00******',
 'J' => '00****0000**0000**0000**0000**0000**0000***000****0**00***00',
 'K' => '**0000****000**0**00**00**0**000****0000****0000**0**000**00**00**000**0**0000**',
 'L' => '**00000**00000**00000**00000**00000**00000**00000**00000**00000*******',
 'M' => '**0000*****00*************0**0****0**0****0**0****0000****0000****0000****0000**',
 'N' => '**0000*****000******00******00****0**0****0**0****00******000*****000*****0000**',
 'P' => '*******0**0000****0000****0000*********0**000000**000000**000000**000000**000000',
 'Q' => '00****000**00**0**0000****0000****0000****0000****0**0****00****0**00**000****0*',
 'R' => '*******0**0000****0000****0000*********0*****000**00**00**000**0**0000****0000**',
 'S' => '0******0**0000****000000**0000000******0000000**000000**000000****0000**0******0',
 'T' => '********000**000000**000000**000000**000000**000000**000000**000000**000000**000',
 'U' => '**0000****0000****0000****0000****0000****0000****0000****0000**0**00**000****00',
 'V' => '**0000****0000****0000**0**00**00**00**00**00**000****0000****00000**000000**000',
 'W' => '**0000****0000****0000****0000****0**0****0**0****0**0*************00*****0000**',
 'X' => '**0000****0000**0**00**000****00000**000000**00000****000**00**0**0000****0000**',
 'Y' => '**0000****0000**0**00**000****00000**000000**000000**000000**000000**000000**000',
 'Z' => '*******00000**00000**0000**0000**0000**0000**0000**00000**00000*******',
 'a' => '00*****00**000**000000**0*********0000****000***0****0**',
 'b' => '**000000**000000**000000**0***00***00**0**0000****0000****0000*****00**0**0***00',
 'c' => '00*****00**000****000000**000000**0000000**000**00*****0',
 'd' => '000000**000000**000000**00***0**0**00*****0000****0000****0000**0**00***00***0**',
 'e' => '00****000**00**0**0000************0000000**000**00*****0',
 'f' => '000****000**00**00**00**00**000000**0000******0000**000000**000000**000000**0000',
 'g' => '0*****0***000*****000**0**000**00*****00**0000000******0**0000**0******0',
 'h' => '**000000**000000**000000**0***00***00**0**0000****0000****0000****0000****0000**',
 'i' => '00**0000**000000000***0000**0000**0000**0000**0000**00******',
 'k' => '**00000**00000**00000**00**0**0**00****000****000**0**00**00**0**000**',
 'l' => '***00**00**00**00**00**00**00**00**0****',
 'm' => '*0**0**0**0**0****0**0****0**0****0**0****0**0****0**0**',
 'n' => '**0***00***00**0**0000****0000****0000****0000****0000**',
 'o' => '00****000**00**0**0000****0000****0000**0**00**000****00',
 'p' => '**0***00***00**0**0000****0000****0000*****00**0**0***00**000000**000000',
 'q' => '00***0**0**00*****0000****0000****0000**0**00***00***0**000000**000000**',
 'r' => '**0****00***00**0**000000**000000**000000**000000**00000',
 's' => '0******0**0000****0000000******0000000****0000**0******0',
 't' => '00**000000**0000******0000**000000**000000**000000**000000**00**000****0',
 'u' => '**0000****0000****0000****0000****0000**0**00***00***0**',
 'v' => '**0000****0000**0**00**00**00**000****0000****00000**000',
 'w' => '**0000****0000****0**0****0**0****0**0**********0**00**0',
 'x' => '**0000**0**00**000****00000**00000****000**00**0**0000**',
 'y' => '**0000****0000****0000****0000****0000**0**00***00***0***00000**0******0',
 'z' => '******0000**000**000**000**000**0000******',
 '0' => '000**00000****000**00**0**0000****0000****0000****0000**0**00**000****00000**000',
 '1' => '00**000***00****0000**0000**0000**0000**0000**0000**00******',
 '2' => '00****000**00**0**0000**000000**00000**00000**00000**00000**00000**00000********',
 '3' => '0*****00**000**0000000**00000**0000***0000000**0000000**000000****000**00*****00',
 '4' => '00000**00000***0000****000**0**00**00**0**000**0********00000**000000**000000**0',
 '5' => '*******0**000000**000000**0***00***00**0000000**000000****0000**0**00**000****00',
 '6' => '00****000**00**0**0000*0**000000**0***00***00**0**0000****0000**0**00**000****00',
 '7' => '********000000**000000**00000**00000**00000**00000**00000**00000**000000**000000',
 '8' => '00****000**00**0**0000**0**00**000****000**00**0**0000****0000**0**00**000****00',
 '9' => '00****000**00**0**0000****0000**0**00***00***0**000000**0*0000**0**00**000****00',
    );

    
    public function make($verCode = '') {
 if(empty($verCode)) {
     $baseChars     = 'ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789';
     $verCode= '';
     $codeCharLenth = 4;
     for ($i = 1; $i <= $codeCharLenth; $i++) {
  // 通过字符串下标形式随机获取
  $verCode .= $baseChars{mt_rand(0, strlen($baseChars) - 1)};
     }
 }

 // 以下代码是将生成的验证码生成图片
 $font_size = 20;
 $width     = 60;
 $height    = 30;
 $img= imagecreate($width, $height); // 新建一个基于调色板的图像

 $bgR = mt_rand(50, 200); //r(ed)
 $bgG = mt_rand(50, 200); //g(reen)
 $bgB = mt_rand(50, 200); //b(lue)
 $background = imagecolorallocate($img, $bgR, $bgG, $bgB); // 背景色
 $black      = imagecolorallocate($img, 0, 0, 0);

 imagestring($img, 5, 9, 8, $verCode, $black); // 水平地画一行字符串

 ob_start();
 imagepng($img);
 $image = ob_get_contents();
 ob_end_clean();

 return array(
     'image' =>  $image,
     'code'  =>  $verCode
 );
    }

    
    public function getImage($imageString) {
 $im = imagecreatefromstring($imageString);

 list($width, $height) = getimagesizefromstring($imageString);

 $image = array();

 for($x = 0;$x < $width;$x++) {
     for($y =0;$y < $height;$y++) {
  $rgb = imagecolorat($im, $x, $y);
  $rgb = imagecolorsforindex($im, $rgb);
  if($rgb['red'] == 0 && $rgb['green'] == 0 && $rgb['blue'] == 0) {
      $image[$y][$x] = '*';
  } else {
      $image[$y][$x] = 0;
  }
     }
 }

 return $image;
    }

    
    public function remove($image) {
 //计算x和y轴的
 $xCount = count($image[0]); //60
 $yCount = count($image); //30

 $xFilter = array();
 for($x = 0;$x < $xCount;$x++) {
     $filter = true;
     for($y = 0;$y < $yCount;$y++) {
  $filter = $filter && ($image[$y][$x] == '0');
     }
     if($filter) {
  $xFilter[] = $x;
     }
 }

 //有字符的列
 $xImage = array_values(array_diff(range(0, 59), $xFilter));

 //存放关键字
 $wordImage = array();

 $preX = $xImage[0] - 1;
 $wordCount = 0;
 foreach($xImage as $xKey => $x) {
     if($x != ($preX + 1)) {
  $wordCount++;
     }
     $preX = $x;

     for($y = 0;$y < $yCount;$y++) {
  $wordImage[$wordCount][$y][$x] = $image[$y][$x];
     }
 }

 foreach($wordImage as $key=>$image) {
     $wordImage[$key] = $this->removeByLine($image);
 }


 return $wordImage;

    }

    
    public function removeByLine($image) {

 $isFilter = false;
 foreach($image as $y => $yImage) {
     if($isFilter == true || array_filter($yImage)) {
  $isFilter = true;
     } else {
  unset($image[$y]);
     }
 }

 krsort($image);

 $isFilter = false;
 foreach($image as $y => $yImage) {
     if($isFilter == true || array_filter($yImage)) {
  $isFilter = true;
     } else {
  unset($image[$y]);
     }
 }

 ksort($image);

 return $image;
    }

    
    public function getWordString($wordImage) {
 $wordString = '';
 foreach($wordImage as $image) {
     foreach($image as $string) {
  $wordString .= $string;
     }
 }

 return $wordString;
    }

    
    public function match($image) {
 $match = array(
     'min' => '',
     'key' => ''
 );
 foreach($this->_wordKeys as $k => $v) {
     $percent = 0.0;
     similar_text($this->getWordString($image), $v, $percent);
     if($match['min'] == '') {
  $match['min'] = $percent;
  $match['key'] = $k;
     } else {
  if($percent > $match['min']) {
      $match['min'] = $percent;
      $match['key'] = $k;
  }
     }
 }

 return $match;
    }

    
    public function show($image) {
 foreach($image as $xImage) {
     foreach($xImage as $yImage) {
  echo $yImage;
     }
     echo PHP_EOL;
 }
 echo PHP_EOL;
    }
}


$vCode = new vCode();

$codeImage = $vCode->make();
$imageString = $codeImage['image'];

$image = $vCode->getImage($imageString);
//原图
$vCode->show($image);

//去除干扰边框、拆字
$newImage = $vCode->remove($image);
$word = array();
$code = '';
foreach($newImage as $image) {
    $vCode->show($image);
    $code .= $vCode->match($image)['key'];
}

echo "生成的验证码为:{$codeImage['code']}" . PHP_EOL;
echo "识别的验证码为:{$code}" . PHP_EOL;


运行结果:


7b8866871584234e368769cef033e41.png

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/262527.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号