一種低成本的找回密碼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。

相關文章
相關標籤/搜索