设为首页 收藏本站
查看: 1352|回复: 0

[经验分享] 使用php生成验证码

[复制链接]

尚未签到

发表于 2017-3-29 12:05:34 | 显示全部楼层 |阅读模式
很久没发blog了,呵呵,今天讨论一下验证码生成的问题。
常上网的人都知道很多网站在发帖时都要输入验证码,这是因为网站为防止别人使用程序在网站上自动发布大量的垃圾信息(如果是人为的危害就不是太大,不可能短时间发个几千甚至上万信息)。因此就诞生了验证码,在发贴时要验证码正确才能发表成功。这方法大概是现在为止最简单有效的方法了,因为要使用程序去辨认上面的字符难度系数相当高。我使用php写了个验证码生成程序,生成的验证码效果如下:
DSC0000.jpg
程序比较简单。原理就是先产生4个随机数,将4个数字生成图片,并将图片进行一定角度的旋转,再合成为一副图片,再加上干扰点和线,考虑到便于用户辨认只使用了数字,干扰线也不能使用太多,这里用了5条。有些网站还有大小写的字母,(呵呵,如果你想让使用户为辨认上面的字符而感到头疼就这么干)。
该方法的缺点是:不是每次产生的图片用户都容易辨认,因此在使用时要考虑用户可以跟换图片,就如新浪blog在发表评论那样。实现的代码如下:
function RgbToHsv($R, $G, $B)
{
<wbr>// r,g,b values are from 0 to 1<br><wbr> // h = [0,360], s = [0,1], v = [0,1]<br><wbr> // if s == 0, then h = -1 (undefined)</wbr></wbr></wbr>
  <wbr>$tmp = min($R, $G);<br><wbr> $min = min($tmp, $B);<br><wbr> $tmp = max($R, $G);<br><wbr> $max = max($tmp, $B);<br><wbr> $V = $max;<br><wbr> $delta = $max - $min;</wbr></wbr></wbr></wbr></wbr></wbr>
  <wbr> if($max != 0)<br><wbr><wbr>$S = $delta / $max; // s<br><wbr> else<br><wbr> {<br><wbr><wbr>$S = 0;<br><wbr><wbr><wbr> //$H = UNDEFINEDCOLOR;<br><wbr><wbr><wbr> return;<br><wbr> }<br><wbr> if($R == $max)<br><wbr><wbr>$H = ($G - $B) / $delta; // between yellow &amp; magenta<br><wbr> else if($G == $max)<br><wbr><wbr><wbr> $H = 2 + ($B - $R) / $delta; // between cyan &amp; yellow<br><wbr><wbr>else<br><wbr><wbr><wbr> $H = 4 + ($R - $G) / $delta; // between magenta &amp; cyan</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
  <wbr> $H *= 60; // degrees<br><wbr> if($H &lt; 0)<br><wbr><wbr>$H += 360;<br><wbr><wbr>return array($H, $S, $V);<br>}</wbr></wbr></wbr></wbr></wbr></wbr>
  function HsvToRgb($H, $S, $V)
{
<wbr>if($S == 0)<br><wbr> {<br><wbr><wbr>// achromatic (grey)<br><wbr><wbr>$R = $G = $B = $V;<br><wbr><wbr><wbr> return;<br><wbr> }</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
  <wbr> $H /= 60;<wbr><wbr>// sector 0 to 5<br><wbr> $i = floor($H);<br><wbr> $f = $H - $i;<wbr><wbr>// factorial part of h<br><wbr> $p = $V * (1 - $S);<br><wbr> $q = $V * (1 - $S * $f);<br><wbr> $t = $V * (1 - $S * (1 - $f));</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
  <wbr> switch($i)<br><wbr> {<br><wbr><wbr>case 0:<br><wbr><wbr><wbr><wbr>$R = $V;<br><wbr><wbr><wbr><wbr><wbr> $G = $t;<br><wbr><wbr><wbr><wbr><wbr> $B = $p;<br><wbr><wbr><wbr><wbr><wbr> break;<br><wbr><wbr><wbr> case 1:<br><wbr><wbr><wbr><wbr><wbr> $R = $q;<br><wbr><wbr><wbr><wbr><wbr> $G = $V;<br><wbr><wbr><wbr><wbr><wbr> $B = $p;<br><wbr><wbr><wbr><wbr><wbr> break;<br><wbr><wbr><wbr> case 2:<br><wbr><wbr><wbr><wbr><wbr> $R = $p;<br><wbr><wbr><wbr><wbr><wbr> $G = $V;<br><wbr><wbr><wbr><wbr><wbr> $B = $t;<br><wbr><wbr><wbr><wbr><wbr> break;<br><wbr><wbr><wbr> case 3:<br><wbr><wbr><wbr><wbr><wbr> $R = $p;<br><wbr><wbr><wbr><wbr><wbr> $G = $q;<br><wbr><wbr><wbr><wbr><wbr> $B = $V;<br><wbr><wbr><wbr><wbr><wbr> break;<br><wbr><wbr><wbr> case 4:<br><wbr><wbr><wbr><wbr><wbr> $R = $t;<br><wbr><wbr><wbr><wbr><wbr> $G = $p;<br><wbr><wbr><wbr><wbr><wbr> $B = $V;<br><wbr><wbr><wbr><wbr><wbr> break;<br><wbr><wbr><wbr> default: // case 5:<br><wbr><wbr><wbr><wbr><wbr> $R = $V;<br><wbr><wbr><wbr><wbr><wbr> $G = $p;<br><wbr><wbr><wbr><wbr><wbr> $B = $q;<br><wbr><wbr><wbr><wbr><wbr> break;<br><wbr>}<br><wbr> return array($R, $G, $B);<br>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
  $size = 20;
$width = 80;
$height = 25;
// 产生4个随机字符
  $randStr =array(rand(0, 9), rand(0, 9), rand(0, 9), rand(0, 9));<wbr><wbr></wbr></wbr>
  // 生成数字旋转角度
  $degrees = array(rand(0, 45), rand(0, 45), rand(0, 45), rand(0, 45));<wbr></wbr>
  for($i = 0; $i < 4; ++$i)
{
<wbr>if(rand() % 2);<br><wbr>else $degrees[$i] = -$degrees[$i];<br>}</wbr></wbr>
  $image = imagecreatetruecolor($size, $size);<wbr><wbr><wbr>// 数字图片画布<br>$validate = imagecreatetruecolor($width, $height);<wbr><wbr>// 最终验证码画布<br>$back = imagecolorallocate($image, 255, 255, 255);<wbr><wbr>// 背景色<br>$border = imagecolorallocate($image, 0, 0, 0);<wbr><wbr><wbr><wbr>// 边框</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
  // 数字颜色
for($i = 0; $i < 4; ++$i)
{
<wbr>// 考虑为使字符容易看清使用颜色较暗的颜色<br><wbr>$temp = RgbToHsv(rand(0, 255), rand(0, 255), rand(0, 255));<br><wbr><br><wbr>if($temp[2] &gt; 60)<br><wbr><wbr>$temp [2] = 60;</wbr></wbr></wbr></wbr></wbr></wbr>
  <wbr>$temp = HsvToRgb($temp[0], $temp[1], $temp[2]);<br><wbr>$textcolor[$i] = imagecolorallocate($image, $temp[0], $temp[1], $temp[2]);<br>}</wbr></wbr>
  imagefilledrectangle($validate, 0, 0, $width - 1, $height - 1, $back);<wbr><wbr>// 画出背景色<br>imagefilledrectangle($image, 0, 0, $size, $size, $back);<wbr>// 画出背景色<wbr><br>imagestring($image, 5, 6, 2, $randStr[0], $textcolor[0]);<wbr><wbr>// 画出数字<br>$image = imagerotate($image, $degrees[0], $back);<br>imagecopy($validate, $image, 1, 4, 4, 5, imagesx($image) - 10, imagesy($image) - 10);</wbr></wbr></wbr></wbr></wbr></wbr>
  $image = imagecreatetruecolor($size, $size);
imagefilledrectangle($image, 0, 0, $size, $size, $back);<wbr><wbr>// 画出背景色<wbr><br>imagestring($image, 5, 6, 2, $randStr[1], $textcolor[1]);<wbr><wbr>// 画出数字<br>$image = imagerotate($image, $degrees[1], $back);<br>imagecopy($validate, $image, 21, 4, 4, 5, imagesx($image) - 10, imagesy($image) - 10);</wbr></wbr></wbr></wbr></wbr>
  $image = imagecreatetruecolor($size, $size);
imagefilledrectangle($image, 0, 0, $size - 1, $size - 1, $back);<wbr><wbr>// 画出背景色<wbr><br>imagestring($image, 5, 6, 2, $randStr[2], $textcolor[2]);<wbr><wbr>// 画出数字<br>$image = imagerotate($image, $degrees[2], $back);<br>imagecopy($validate, $image, 41, 4, 4, 5, imagesx($image) - 10, imagesy($image) - 10);</wbr></wbr></wbr></wbr></wbr>
  $image = imagecreatetruecolor($size, $size);
imagefilledrectangle($image, 0, 0, $size - 1, $size - 1, $back);<wbr><wbr>// 画出背景色<wbr><br>imagestring($image, 5, 6, 2, $randStr[3], $textcolor[3]);<wbr><wbr>// 画出数字<br>$image = imagerotate($image, $degrees[3], $back);<br>imagecopy($validate, $image, 61, 4, 4, 5, imagesx($image) - 10, imagesy($image) - 10);<br>imagerectangle($validate, 0, 0, $width - 1, $height - 1, $border);<wbr><wbr>// 画出边框</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
  for($i = 0; $i < 200; ++$i) //加入干扰象素
{
<wbr>$randpixelcolor = ImageColorallocate($validate, rand(0, 255), rand(0, 255), rand(0, 255));<br><wbr>imagesetpixel($validate, rand(1, 87), rand(1, 27), $randpixelcolor);<br>}</wbr></wbr>
  // 干扰线使用颜色较明亮的颜色
$temp = RgbToHsv(rand(0, 255), rand(0, 255), rand(0, 255));
  if($temp[2] < 200)
<wbr>$temp [2] = 255;<br><wbr><br>$temp = HsvToRgb($temp[0], $temp[1], $temp[2]);<br>$randlinecolor = imagecolorallocate($image, $temp[0], $temp[1], $temp[2]);<br>// 画5条干扰线<br>for ($i = 0;$i &lt; 5; $i ++)<br><wbr>imageline($validate, rand(1, 79), rand(1, 24), rand(1, 79), rand(1, 24), $randpixelcolor);</wbr></wbr></wbr>
  header('Content-type: image/png');
imagepng($validate);
imagedestroy($validate);
  最后讨论一下新浪博客中的“收听验证码”,呵呵,看起来好像很复杂,考虑了一下,其实要实现也挺简单的,将单个数字录成mp3格式的声音文件,使用windows media player根据产生的数字播放出来(网页中嵌入个object)。考虑兼容问题最好使用flash播放。
  提示一下:程序中有Rgb到Hsv颜色互换函数。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-357055-1-1.html 上篇帖子: PHP 初学者的30+最佳实践 下篇帖子: 论PHP和.Net 哪个更有前景
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表