Appcode.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. namespace tncode;
  3. /**
  4. * APP专用行为验证码
  5. */
  6. class Appcode
  7. {
  8. protected $_fault = 4; //容错象素 越大体验越好,越小破解难道越高
  9. protected $error_num = 2; //验证图形验证码时,错误次数不能超过2次
  10. protected $yzm_time = 180; //设置失效时间 180=3分钟
  11. protected $sid = '';
  12. public function __construct($sid=''){
  13. $this->sid = $sid?:md5($_SERVER['HTTP_USER_AGENT'].$_SERVER['REMOTE_ADDR']);
  14. session_id($this->sid);//指定一个session 的id
  15. session_start();//开启session
  16. }
  17. /**
  18. * 刷新图片
  19. */
  20. public function refresh(){
  21. //【随机】裁剪的区域坐标【左上角】【并保存】
  22. $_SESSION['tuxing_yzm_x'] = rand(30,530);
  23. $_SESSION['tuxing_yzm_y'] = rand(50, 250);
  24. $_SESSION['tuxing_yzm_img'] = __DIR__.'/appbg/'.rand(1, 3).'.jpg';//原图要求是 1920x1080这个比例的,679x382【图片避免用白色背景的】
  25. $_SESSION['tuxing_yzm_moban'] = __DIR__.'/appbg/icon/'.rand(1, 4).'.png';
  26. $_SESSION['tuxing_yzm_opacity'] = rand(30, 80);//原图上空缺的位置的透明度【这个可以增加被破解的记录】
  27. $_SESSION['tuxing_yzm_time'] = time() + $this->yzm_time;
  28. $_SESSION['tuxing_yzm_error_cishu'] = $this->error_num;
  29. return $this->sid;
  30. }
  31. /**
  32. * 验证图片位置
  33. * @param string $offset 位置数值
  34. * @return string|boolean
  35. */
  36. public function check($offset=''){
  37. if(!(isset($_SESSION['tuxing_yzm_x']) && isset($_SESSION['tuxing_yzm_error_cishu']) && isset($_SESSION['tuxing_yzm_time']) )){
  38. return '请先获取图形验证码';
  39. }
  40. if($_SESSION['tuxing_yzm_time'] <= time()){
  41. return '验证码已过期,有效期为3分钟';
  42. }
  43. if(!preg_match('/^[0-9]{1,4}$/', $offset)){
  44. return '位置的字符类型有误';
  45. }
  46. if($offset <= $_SESSION['tuxing_yzm_x']+$this->_fault && $offset >= $_SESSION['tuxing_yzm_x']-$this->_fault){//左右两边都有4px的包容度
  47. return true;
  48. }else{
  49. $_SESSION['tuxing_yzm_error_cishu'] -= 1;
  50. if($_SESSION['tuxing_yzm_error_cishu'] == 0){
  51. return '验证码错误次数过多,请重新获取';
  52. }
  53. return '图形滑块验证码位置有误';
  54. }
  55. }
  56. /**
  57. * 获取背景图或缺口图
  58. * @param string $is_bgimg false为缺口图 true为背景图
  59. * @return string
  60. */
  61. public function img($is_bgimg=true){
  62. if(!( isset($_SESSION['tuxing_yzm_x']) && isset($_SESSION['tuxing_yzm_y']) && isset($_SESSION['tuxing_yzm_img']) && isset($_SESSION['tuxing_yzm_moban']) && isset($_SESSION['tuxing_yzm_opacity']) )){
  63. return '图形滑动验证码尚未生成';
  64. }
  65. $x = $_SESSION['tuxing_yzm_x'];//设置验证码
  66. $y = $_SESSION['tuxing_yzm_y'];//设置验证码
  67. $img = $_SESSION['tuxing_yzm_img'];
  68. $moban = $_SESSION['tuxing_yzm_moban'];
  69. $opacity = $_SESSION['tuxing_yzm_opacity'];
  70. //创建源图的实例
  71. $src = imagecreatefromstring(file_get_contents($img));
  72. //新建一个真彩色图像【尺寸 = 90x90】【目前是不透明的】
  73. $res_image = imagecreatetruecolor(90, 90);
  74. //创建透明背景色,主要127参数,其他可以0-255,因为任何颜色的透明都是透明
  75. $transparent = imagecolorallocatealpha($res_image, 255, 255, 255, 127);
  76. //指定颜色为透明(做了移除测试,发现没问题)
  77. imagecolortransparent($res_image, $transparent);
  78. //填充图片颜色【填充会将相同颜色值的进行替换】
  79. imagefill($res_image, 0, 0, $transparent);//左边的半圆
  80. //实现两个内凹槽【填补上纯黑色】
  81. $tempImg = imagecreatefrompng($moban);//加载模板图
  82. for($i=0; $i < 90; $i++){// 遍历图片的像素点
  83. for ($j=0; $j < 90; $j++) {
  84. if(imagecolorat($tempImg, $i, $j) !== 0){// 获取模板上某个点的色值【取得某像素的颜色索引值】【0 = 黑色】
  85. $rgb = imagecolorat($src, $x + $i, $y + $j);// 对应原图上的点
  86. imagesetpixel($res_image, $i, $j, $rgb);// 移动到新的图像资源上
  87. }
  88. }
  89. }
  90. if($is_bgimg){ //背景图
  91. //制作一个半透明白色蒙版
  92. $mengban = imagecreatetruecolor(90, 90);
  93. //先让蒙版变成透明的
  94. //指定颜色为透明(做了移除测试,发现没问题)
  95. imagecolortransparent($mengban, $transparent);
  96. //填充图片颜色【填充会将相同颜色值的进行替换】
  97. imagefill($mengban, 0, 0, $transparent);
  98. $huise = imagecolorallocatealpha($res_image, 255, 255, 255, $opacity);
  99. for($i=0; $i < 90; $i++){// 遍历图片的像素点
  100. for ($j=0; $j < 90; $j++) {
  101. $rgb = imagecolorat($res_image, $i, $j); // 获取模板上某个点的色值【取得某像素的颜色索引值】
  102. if($rgb !== 2147483647){// 获取模板上某个点的色值【取得某像素的颜色索引值】【0 = 黑色】
  103. imagesetpixel($mengban, $i, $j, $huise);// 对应点上画上黑色
  104. }
  105. }
  106. }
  107. //把修改后的图片,放回原本的位置
  108. imagecopyresampled(
  109. $src,//裁剪后的存放图片资源
  110. $res_image,//裁剪的原图资源
  111. $x, $y,//存放的图片,开始存放的位置
  112. 0,0,//开始裁剪原图的位置
  113. 90, 90,//存放的原图宽高
  114. 90, 90//裁剪的原图宽高
  115. );
  116. //把蒙版添加到原图上去
  117. imagecopyresampled(
  118. $src,//裁剪后的存放图片资源
  119. $mengban,//裁剪的原图资源
  120. $x+1, $y+1,//存放的图片,开始存放的位置
  121. 0,0,//开始裁剪原图的位置
  122. 90-2, 90-2,//存放的原图宽高
  123. 90, 90//裁剪的原图宽高
  124. );
  125. header('Content-Type: image/jpeg');
  126. imagejpeg($src);//浏览器 输出图片
  127. }else{ //缺口图
  128. //补上白色边框
  129. $tempImg = imagecreatefrompng($moban.'.png');//加载模板图
  130. $white = imagecolorallocatealpha($res_image, 255, 255, 255, 1);
  131. for($i=0; $i < 90; $i++){// 遍历图片的像素点
  132. for ($j=0; $j < 90; $j++) {
  133. if(imagecolorat($tempImg, $i, $j) === 0){// 获取模板上某个点的色值【取得某像素的颜色索引值】【0 = 黑色】
  134. imagesetpixel($res_image, $i, $j, $white);// 对应点上画上黑色
  135. }
  136. }
  137. }
  138. //创建一个90x382宽高 且 透明的图片
  139. $res_image2 = imagecreatetruecolor(90, 382);
  140. //指定颜色为透明(做了移除测试,发现没问题)
  141. imagecolortransparent($res_image2, $transparent);
  142. //填充图片颜色【填充会将相同颜色值的进行替换】
  143. imagefill($res_image2, 0, 0, $transparent);//左边的半圆
  144. //把裁剪的图片,移到新图片上
  145. imagecopyresampled(
  146. $res_image2,//裁剪后的存放图片资源
  147. $res_image,//裁剪的原图资源
  148. 0, $y,//存放的图片,开始存放的位置
  149. 0, 0,//开始裁剪原图的位置
  150. 90, 90,//存放的原图宽高
  151. 90, 90//裁剪的原图宽高
  152. );
  153. header('Content-Type: image/png');
  154. imagepng($res_image2);//浏览器 输出图片
  155. }
  156. }
  157. }