前言:
对于验证码,常规的做法是在服务端生成字符串以及字符串图片,把字符串存在session文件中,字符串图片也就是验证码图片发给客户端,客户端根据图片发送相应的字符串到服务器,服务器将客户发来的字符串跟session文件的字符串做对比,以此来判断是验证码是否正确。
这样的做法会导致一个问题,如果访问的用户多了,服务器就要生成很多session文件,效率也会逐渐降低。
而群里大神说的技巧就是把验证码存储在客户端!具体看下面的代码:
程序:
1. 目录文件
2. 验证码页面 index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .verify_code{ width:150px; height:70px; } </style> </head> <body> <form action="check.php" method="post"> 验证码: <img src="output.php" alt="" class="verify_code" onclick="this.src='output.php?'+Math.random()"><br><br> <input type="text" name="verify_code" /><br> <input type="submit" value="提交" /> </form> </body> </html>
3. 输出验证码接口文件 output.php
include_once 'function.php'; //验证码 $verifycode = randStr(5); //加密盐 $salt = randStr(4); $md5_code = encrypt($verifycode, $salt); //设置cookie setcookie('md5_code',$md5_code); setcookie('salt',$salt); //设置验证码过期时间,5分钟 setcookie('expire_time',time() + 300); //生成验证码图片输出 createImg($verifycode);
4. 公共函数文件 function.php
//返回随机字符串 function randStr($length){ $str = '1234567890qwertyuiQWERTYUI'; return substr(str_shuffle($str),1,$length); } //加密函数 function encrypt($code, $salt){ return md5(strtolower($code) . md5($salt)); } //生成验证码图片 function createImg($code){ //省略代码 }
5. 验证判断文件 check.php
include_once 'function.php'; $verifycode = strtolower($_POST['verify_code']); $salt = $_COOKIE['salt']; $md5_code = $_COOKIE['md5_code']; $expire_time = $_COOKIE['expire_time']; if($expire_time < time()){ echo '<h2>验证码已失效,请重试,正在跳转...</h2>'; header('refresh:3;url=index.html'); } if(encrypt($verifycode, $salt) == $md5_code){ echo '<h2>验证码正确</h2>'; }else{ echo '<h2>验证码错误,正在跳转...</h2>'; header('refresh:3;url=index.html'); }
6. 具体分析
a. 使用md5(strtolower($code) . md5($salt))把验证码加盐加密,加密后的字符串存储在客户端cookie里
b. salt明文存储在cookie中
c. expire_time过期时间存储在cookie中
这种存储方式的核心是用户很难猜测服务端是怎么加密的,所以更加不可能利用机器暴力破解验证码。我这里的md5(strtolower($code) . md5($salt))只是一种比较简单的加密方式,你还可以用其他的方式,例如md5(md5($salt) . strtolower($code) . md5($salt))等等。
来自ansion博客
2017-11-15 14:02:51