一种低成本的找回密码token验证方案

随着互联网的高速发展,WEB2.0网站的业务愈来愈庞大,一些token验证在许多场景下都必不可少,好比说交易订单的防止屡次提交,重要的敏感操做防止CSRF(跨站请求伪造)攻击,以及短信验证码,找回密码验证码,注册登陆图形的生成和验证。
token的特色主要有以下几个:算法

  1. 惟一性后端

  2. 时效性缓存

  3. 不可预测安全

不少大型业务中,好比说BAT的找回密码流程中,对于发给用户的找回密码连接邮件须要同时提交用户输入的vcode验证码和vcode_md5也就是该校验码对应的token。不少人认为这时须要一个缓存中间件好比说Redis或者Memcache来存储校验码对应的须要重置密码的用户Uid。其实大可没必要如此。服务器

咱们能够在服务器端使用rand()生成随机数,而后将生成的随机数加上指定的salt作md5处理,好比说cookie

function vcode($uid) {
    $output['vcode_timestamp'] = time();
    $output['vcode'] = $uid;
    $output['vcode_md5'] = md5("changwei"+vcode_timestamp+$uid);
    return $output;
}

生成的时候将vcode和vcode_md5一块儿经过邮件发回给客户。session

那么验证的时候该怎么验证呢?很好办,把指定的盐值加上校验码以及其余附带信息(好比说用户UID)进行md5运算,和客户端提交的那个事先发给客户端的vcode_md5进行比较,若是一致那么就经过。并发

那么咱们来看看这是否具备token的几个特色呢?首先,惟一性,能够经过uid(这个通常是用户表的递增主键,不会重复),而且将当前时间戳做为随机数种子,基本上能够认为是高度随机的数字了,加上md5加盐运算以后客户有视为高度近似的惟一性了。不可预测性呢?因为指定的salt是存储在服务端,只要这个salt足够复杂并且没有被泄漏,那么这个vcode_md5确定是没法被客户端预测的,也保证了这个方案的安全性。高并发

最后就是时效性了,不少人总在纠结,若是没有Redis或Memcache,那么如何去存储他的时效性呢?经过cookie吗?不行,cookie是在客户端的,那么意味着是用户可控的,不安全。用session呢?标题写了是低成本解决方案,session存储在服务端,在高并发请求数量庞大的大型网站中,每时每刻都有成千上万的校验码生成,若是都存在session对于服务器压力(尤为是IO)是十分大的。那么还有什么办法呢?咱们想一想,既然md5是消息摘要算法,那么他就能够用来验证数据在传输中途是否通过了篡改,那么思路就来了,咱们在发回给用户的表单中再加一个隐藏域,名字为vcode_timestamp,后端算法再改一改,此次提供完整的验证算法源代码。测试

function vcode($uid) {
    $output['vcode_timestamp'] = time();
    $output['vcode'] = $uid;
    $output['vcode_md5'] = md5("changwei"+vcode_timestamp+$uid);
    return $output;
}
function verify() {
    if(md5("changwei"+$_POST['vcode_timestamp']+$_POST['uid'])===$_POST['vcode_md5']) {
        if(time()<intval($_POST['vcode_timestamp'])+60*60){ // 60*60表示时效性为一个小时
                return true;
            }
        return false;
        }
    return false;
}

这样一来时效性也能够验证了,全过程没有涉及到任何服务器端的存储引擎,能够说是把成本降到了最低。并且md5自己也是目前效率很是高的hash算法,对于cpu的消耗也不是很大。

目前个人网站lol.changwei.me

中取消监控连接便用的是该方案,通过上线一个月的测试,基本上没有出现什么BUG。

相关文章
相关标签/搜索