Page

[优化]巧用加密实现纯客户端存储验证码

727Anson17-11-15


昨晚群里的大神告诉我们一个存储验证码的技巧:把验证码存储在客户端。

前言:

    对于验证码,常规的做法是在服务端生成字符串以及字符串图片,把字符串存在session文件中,字符串图片也就是验证码图片发给客户端,客户端根据图片发送相应的字符串到服务器,服务器将客户发来的字符串跟session文件的字符串做对比,以此来判断是验证码是否正确。

这样的做法会导致一个问题,如果访问的用户多了,服务器就要生成很多session文件,效率也会逐渐降低。


    而群里大神说的技巧就是把验证码存储在客户端!具体看下面的代码:



程序:


1. 目录文件

blob.png


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))等等。

    


verifycode.zip



来自ansion博客 

http://www.tp0.top

2017-11-15 14:02:51