PHP对验证码的认证过程防止机器注册

    这段时间在写php脚本,接触到web前端以及web安全问题比较多,这时给大家简单地谈一下我们网站验证码的验证过程及其安全问题。

    从三个方面去谈一下关于验证码的使用:验证码的生成,验证的过程,验证中注意的安全问题。

    验证码的生成,首先还是要说说验证码的作用。众所周知,验证码的存在,是为了防止一些机器,或是刷恶意留言、无限注册用户或是暴力破解账号密码。现在普通的验证码是由一个php脚本生成的,比如打开我们emlog的include/lib/文件夹,底下有个checkcode.php,这就是生成验证码的脚本。

    我们可以简单看一下它的代码:
session_start();

$randCode = '';
$chars = 'abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPRSTUVWXYZ23456789';
for ( $i = 0; $i < 5; $i++ ){
 $randCode .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}

$_SESSION['code'] = strtoupper($randCode);

$img = imagecreate(70,22);
$bgColor = isset($_GET['mode']) && $_GET['mode'] == 't' ? imagecolorallocate($img,245,245,245) : imagecolorallocate($img,255,255,255);
$pixColor = imagecolorallocate($img,mt_rand(30, 180), mt_rand(10, 100), mt_rand(40, 250));

for($i = 0; $i < 5; $i++){
 $x = $i * 13 + mt_rand(0, 4) - 2;
 $y = mt_rand(0, 3);
 $text_color = imagecolorallocate($img, mt_rand(30, 180), mt_rand(10, 100), mt_rand(40, 250));
 imagechar($img, 5, $x + 5, $y + 3, $randCode[$i], $text_color);
}
for($j = 0; $j < 60; $j++){
 $x = mt_rand(0,70);
 $y = mt_rand(0,22);
 imagesetpixel($img,$x,$y,$pixColor);
}

header('Content-Type: image/png');
imagepng($img);
imagedestroy($img);

    第一个for循环在$chars这个字符串中随机取了5个字符,这实际上就是我们的真实验证码。然后我们可以看到:$_SESSION['code'] = strtoupper($randCode); 他把我们的验证码转换成大写赋值到session里了。

    有的朋友要问,问什么赋值到SESSION里了不赋值到COOKIE里。这就说明你对他们二者关系不了解。cookie和session都作为网站临时保存客户端相关信息的一个“容器”,但是cookie是保存在客户端里的,也就是网站的访问者可以随意查看和修改cookie里的内容,那就没有验证码存在的意义了,因为用户可以直接从cookie中读到验证码,当然机器也可以。而session是保存在服务器上的内容,我生成好的验证码,用户不可能读取到。

    再看源码,后面的两个循环分别是生成彩色的带验证码的图片和在图片上加噪点。是为了加大机器识别验证码的难度。最后我们看到,header('Content-Type: image/png'); 把我们这个页面定义成为图片的格式。

    这样,我们就可以用html代码来让验证码显示出来:

<img src="checkcode.php" />

     类似这样:
    那么验证的过程就是,我们首先生成5个随机字符,保存到session里。然后把这5个字符画成一个图片给用户看,让用户识别,填写在表单里提交后和我们session里的验证码比对。

    其实就是这么简单。

    最后来说说验证码的安全性。我们emlog和wordpress其实验证码并不是很强大,我们这个简单的验证码可以写一个小脚本很容易地识别,所以并不适合比较大型的网站使用。像类似腾讯、百度这种网站的验证码很多字符能旋转、扭曲,并且背影上的干扰物更多,甚至是中文验证码。不过对于小型网站来说,普通等级的验证码足矣防范很多刷评论的机器。

    还有一点很重要,注意验证码使用过后要记住删除相应的session。否则验证码就失去了其意义,这也是我之前犯过的错误。

    为什么这么说。作为一个正常用户,我们每访问一次需要填写验证码的页面,生成验证码的脚本都会执行一次,也就说会生成一个新验证码赋值到session里,没有任何问题。但对于一个机器(或一个暴力破解密码脚本),它第一次访问需要填写验证码的页面,然后在session中得到一个验证码,它以后就不用再次访问这个页面了。直接把第一次的数据包更改并再次发送即可,于是,如果没有清除session的网站,每次的验证码都和第一次相同,也就丧失了验证码的本来作用。

    这是我们做网站需要注意的地方。希望大家在写程序的时候多注意网站的安全性,避免在网站发布后出现问题

 

通过网上的一些实例,拼凑出一个验证码登陆测试程序。详细代码如下:

生成验证码程序ttt.php。通过random生成随机数,然后保存在session里:

 

login.htm页面

 

<html>
<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head>
<title>login</title>
<style type="text/css">
<!--
.textbox {
height: 18px;
width: 100px;
}
.text {
font-size: 14px;
vertical-align: bottom;
color: #0000FF;
}
.style1 {
font-size: 18px;
color: #0000FF;
font-family: "幼圆";
}
-->
</style>
</head>
<body>
<table width="200">
<tr><td align="center" valign="bottom" class="style1" bgcolor="#C7D3F9">请输入验证码</td>
</tr>
</table>
<form method="post" action="login.php">
<table width="200" border="0" bgcolor="C7D3F9">
  <tr>
    <td class="text">验证码:</td>
    <td align="right" valign="bottom"><input type="text" name="auth" class="textbox"></td>
  </tr>
</table>
<img src="ttt.php?act=yes" align="middle">
<table width="200"><tr><td align="right"><input type="button" value="看不清楚验证码" onclick="window.location.reload();"><input name="submit" type="submit" value="Submit"></td></tr></table>
</form>
</body>
</html>

login.php

<?php
session_start();
$name = $_POST['user'];
$password = $_POST['passwd'];
$auth = $_POST['auth'];
#require("db.php");
#$db = new db();
#$sql = "select * from user where name = '$name' and password = '$password'";
#$result = $db->query($sql);
if($_SESSION['seccode'] == $auth)
{
  #$_SESSION['user'] = $name;
  #$_SESSION['passwd'] = $password;
 # header("Location: main.php");
#echo ("登录成功!");

$_SESSION['seccode']='';
  print '
  <script language=javascript>
   alert("登录成功!");
  </script>';
}else
{
  print '
  <script language=javascript>
   alert("登录失败,请重新登录!");
   self.window.location="login.html";
  </script>';
}
?>

ttt.php验证码生成程序

<?php
session_start();

function random($length, $numeric = 0) {
 mt_srand((double)microtime() * 1000000);
 if($numeric) {
  $hash = sprintf('%0'.$length.'d', mt_rand(0, pow(10, $length) - 1));
 } else {
  $hash = '';
  $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
  $max = strlen($chars) - 1;
  for($i = 0; $i < $length; $i++) {
   $hash .= $chars[mt_rand(0, $max)];
  }
 }
 return $hash;
}

#if(preg_replace("/https?:\/\/([^\:\/]+).*/i", "\\1", $_SERVER['HTTP_REFERER']) != preg_replace("/([^\:]+).*/", "\\1", $_SERVER['HTTP_HOST'])) {
# exit('Access Denied');
#}

 

//if($_GET['update']) {
 $seccode = random(4, 1);
//}

#if($seccode < 1 || $seccode > 9999) {
# exit('Access Denied');
#}

$_SESSION['seccode'] = $seccode;
$seccode = sprintf('%04d', $seccode);

if(!$nocacheheaders) {
 @header("Expires: -1");
 @header("Cache-Control: no-store, private, post-check=0, pre-check=0, max-age=0", FALSE);
 @header("Pragma: no-cache");
}

if(function_exists('imagecreate') && function_exists('imagecolorset') && function_exists('imagecopyresized') && function_exists('imagecolorallocate') && function_exists('imagesetpixel') && function_exists('imagechar') && function_exists('imagecreatefromgif') && function_exists('imagepng')) {

 $im = imagecreate(62, 25);
 $backgroundcolor = imagecolorallocate ($im, 255, 255, 255);

 $numorder = array(1, 2, 3, 4);
 shuffle($numorder);
 $numorder = array_flip($numorder);

 for($i = 1; $i <= 4; $i++) {
  $imcodefile = 'seccode/'.$seccode[$numorder[$i]].'.gif';
  $x = $numorder[$i] * 13 + mt_rand(0, 4) - 2;
  $y = mt_rand(0, 3);
  if(file_exists($imcodefile)) {
   $imcode = imagecreatefromgif($imcodefile);
   $data = getimagesize($imcodefile);
   imagecolorset($imcode, 0 ,mt_rand(50, 255), mt_rand(50, 128), mt_rand(50, 255));
   imagecopyresized($im, $imcode, $x, $y, 0, 0, $data[0] + mt_rand(0, 6) - 3, $data[1] + mt_rand(0, 6) - 3, $data[0], $data[1]);
  } else {
   $text_color = imagecolorallocate($im, mt_rand(50, 255), mt_rand(50, 128), mt_rand(50, 255));
   imagechar($im, 5, $x + 5, $y + 3, $seccode[$numorder[$i]], $text_color);
  }
 }

 $linenums = mt_rand(10, 32);
 for($i=0; $i <= $linenums; $i++) {
  $linecolor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
  $linex = mt_rand(0, 62);
  $liney = mt_rand(0, 25);
  imageline($im, $linex, $liney, $linex + mt_rand(0, 4) - 2, $liney + mt_rand(0, 4) - 2, $linecolor);
 }

 for($i=0; $i <= 64; $i++) {
  $pointcolor = imagecolorallocate($im, mt_rand(50, 255), mt_rand(50, 255), mt_rand(50, 255));
  imagesetpixel($im, mt_rand(0, 62), mt_rand(0, 25), $pointcolor);
 }

 $bordercolor = imagecolorallocate($im , 150, 150, 150);
 imagerectangle($im, 0, 0, 61, 24, $bordercolor);

 header('Content-type: image/png');
 imagepng($im);
 imagedestroy($im);

} else {

 $numbers = array
  (
  0 => array('3c','66','66','66','66','66','66','66','66','3c'),
  1 => array('1c','0c','0c','0c','0c','0c','0c','0c','1c','0c'),
  2 => array('7e','60','60','30','18','0c','06','06','66','3c'),
  3 => array('3c','66','06','06','06','1c','06','06','66','3c'),
  4 => array('1e','0c','7e','4c','2c','2c','1c','1c','0c','0c'),
  5 => array('3c','66','06','06','06','7c','60','60','60','7e'),
  6 => array('3c','66','66','66','66','7c','60','60','30','1c'),
  7 => array('30','30','18','18','0c','0c','06','06','66','7e'),
  8 => array('3c','66','66','66','66','3c','66','66','66','3c'),
  9 => array('38','0c','06','06','3e','66','66','66','66','3c')
  );

 for($i = 0; $i < 10; $i++) {
  for($j = 0; $j < 6; $j++) {
   $a1 = substr('012', mt_rand(0, 2), 1).substr('012345', mt_rand(0, 5), 1);
   $a2 = substr('012345', mt_rand(0, 5), 1).substr('0123', mt_rand(0, 3), 1);
   mt_rand(0, 1) == 1 ? array_push($numbers[$i], $a1) : array_unshift($numbers[$i], $a1);
   mt_rand(0, 1) == 0 ? array_push($numbers[$i], $a1) : array_unshift($numbers[$i], $a2);
  }
 }

 $bitmap = array();
 for($i = 0; $i < 20; $i++) {
  for($j = 0; $j < 4; $j++) {
   $n = substr($seccode, $j, 1);
   $bytes = $numbers[$n][$i];
   $a = mt_rand(0, 14);
   switch($a) {
    case 1: str_replace('9', '8', $bytes); break;
    case 3: str_replace('c', 'e', $bytes); break;
    case 6: str_replace('3', 'b', $bytes); break;
    case 8: str_replace('8', '9', $bytes); break;
    case 0: str_replace('e', 'f', $bytes); break;
   }
   array_push($bitmap, $bytes);
  }
 }

 for($i = 0; $i < 8; $i++) {
  $a = substr('012', mt_rand(0, 2), 1) . substr('012345', mt_rand(0, 5), 1);
  array_unshift($bitmap, $a);
  array_push($bitmap, $a);
 }

 $image = pack('H*', '424d9e000000000000003e000000280000002000000018000000010001000000'.
   '0000600000000000000000000000000000000000000000000000FFFFFF00'.implode('', $bitmap));

 header('Content-Type: image/bmp');
 echo $image;

}

?>

时间: 2024-11-01 02:59:40

PHP对验证码的认证过程防止机器注册的相关文章

KRACKs漏洞源自WPA2认证过程中 不用担心“邻居”偷你的信息

近日,WPA2协议被发现多个高危漏洞,报道称这些漏洞允许攻击者监听计算机和访问点之间的Wi-Fi流量.有媒体据此解读认为无线上网不安全面临巨大风险.不过360无线电安全研究部总监杨卿表示,KRACKs漏洞成因出在无线协议的WPA2认证过程中,用户不必过度恐慌,他认为: 1,该漏洞Poc利用代码及未公布:2,该漏洞属于范围性影响,需处在合法wifi附近的百米左右的信号范围:3,该漏洞仍属于高级攻击利用,一般人员短时间不具备使用其发动攻击的能力. 所以暂不用担心你的"邻居"会用这个漏洞来偷

欺诈交易开始在Apple Pay中疯狂滋长,银行将加强认证过程

3月4日消息,据<华尔街日报>报道,支付领域研究人员宣称,欺诈交易开始在苹果移动支付Apple Pay中疯狂滋长,欺诈交易数量约占总交易数量的6%,是银行刷卡交易中欺诈交易比重的6倍数. 知情人士透露,随着犯罪分子利用信用卡添加认证过程中存在的漏洞,一些银行开始看到苹果移动支付服务出现日益增多的欺诈交易. 这些人士称,银行开始加强认证过程,以便遏制欺诈行为.这些人士以与苹果签订了保密协议为由不愿具名. Apple Pay中的欺诈问题由支付专家亚伯拉罕(Cherian Abraham)在2月底的

耐思尼克通过ICANN认证 荣升顶级域名注册服务商

近日,中国老牌ISP服务商耐思尼克已通过ICANN认证,正式成为ICANN认证的顶级域名注册服务商.通过ICANN认证后,还将要向VeriSign(受ICANN委托的公司,负责.com/.net/.tv域名的注册管理业务)等管理公司申请相关域名的注册接口,再次对认证企业进行审核. 近日,中国老牌ISP服务商耐思尼克已通过ICANN认证,正式成为ICANN认证的顶级域名注册服务商.从此,耐思尼克将告别代理身份,迈入与万网等企业在内的第一梯队注册商行列. 总经理王征在接受采访时表示,耐思尼克能取得今

验证码的产生过程

Insus.NET实现一个最炫最原创的验证码.你可以从下面的一步一步的演译. 实现一个验证码,需要了解的是,它最基本是随机产生字符串:<在ASP.NET MVC应用程序中随机获取一个字符串>http://www.cnblogs.com/insus/p/3619224.html 随机的字符串准备好,由于是在MVC应用程序实现,还得了解显示图片:<MVC显示Base64图片>http://www.cnblogs.com/insus/p/3621199.html 开始尝试实现<AS

CAS认证(2):认证过程

  国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私募机构九鼎控股打造,九鼎投资是在全国股份转让系统挂牌的公众公司,股票代码为430719,为"中国PE第一股",市值超1000亿元.        ----------------------------------------------------------------------

新浪微博企业认证过程中的授权书应如何填写?

  授权书无固定模板,您可以在搜索引擎中搜索授权书范本.授权书内容须包括但不限于以下内容:委托人与受托人的名称.授权范围.授权期限.法定代表人签字/企业公章.如委托人是个人,同时还需要提交该个人的有效身份证明件(身份证正反面复印件).若授权书为外文,请提供中国翻译公司提供的中文翻译件并加盖翻译公司的公章.

Magento认证工程师考试及注册流程

Magento公司在2011年下半年推出了Magento认证工程师考试, 其分为两个级别Magento Certified Developer和The Magento Certified Developer Plus, 费用都是一样的每科$260. 至于通过考试的好处,我在这里就不多说了, 有兴趣的同学可以看这里: http://www.magentocommerce.com/certification/的关于Benefits描述. 据公司老大4月分参加一年一度的Magento大会" Imagi

耐思尼克荣获ICANN认证成为顶级域名注册商

&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp;  获悉,近日国内知名域名注册服务商耐思尼克已正式通过ICANN认证,这也是中国今年唯一通过ICANN认正的注册商,再加上之前CNNIC认证的国内顶级域名注册商.耐思尼克成为行业里唯数不多通过CNNIC和ICANN双认证的域名顶级服务商,正式迈入一线注册商行列.在当下如此激烈竞争的环境下,耐思尼http://www.iisp.com/?s=lily凭借强大的实力和技术

完善注册机制论坛才能更多的吸引用户

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 对于论坛什么最重要?不是流量,而是注册用户,光有流量,但注册人数并没有体现流量水平的论坛不是成功的论坛,注册人数上去了,但实际活跃会员却很少的论坛也不是一个成功的论坛.注册会员与活跃会员之比越小的论坛,其健康程度和交流的氛围越好.只有做到这点论坛的成功才算迈出了第一步.论坛想要创造一个好的交流平台吸引用户留住用户,不仅仅需要有准确的定位,丰富