Django中csrf token驗證原理

我多年沒維護的博客園,有一篇初學Django時的筆記,記錄了關於django-csrftoekn使用筆記,當時幾乎是照抄官網的使用示例,後來工做全是用的flask。博客園也沒有維護。直到個人博客收到了以下評論,確實把我給問倒了,並且我也仔細研究了這個問題。
1. Django是怎麼驗證csrfmiddlewaretoken合法性的?
2. 每次刷新頁面的時候<input>中的csrf的value都會更新,每次重複登陸的時候cookie的csrf令牌都會刷新,那麼這兩個csrf-token有什麼區別?python

 
image.png

CSRF(Cross Site Request Forgery protection),中文簡稱跨站請求僞造。
django 第一次響應來自某個客戶端的請求時,會在服務器端隨機生成一個 token,把這個 token 放在 cookie 裏。而後每次 POST 請求都會帶上這個 token,
這樣就能避免被 CSRF 攻擊。ajax

這樣子看起來彷佛沒毛病,可是評論中的第三個問題,每次刷新頁面,form表單中的token都會刷新,而cookie中的token卻只在每次登陸時刷新。我對csrftoken的驗證方式起了疑問,後來看了一段官方文檔的解釋。django

When validating the ‘csrfmiddlewaretoken’ field value, only the secret, not the full token, is compared with the secret in the cookie value. This allows the use of ever-changing tokens. While each request may use its own token, the secret remains common to all.
This check is done by CsrfViewMiddleware.flask

官方文檔中說到,檢驗token時,只比較secret是否和cookie中的secret值同樣,而不是比較整個token。
我又有疑問了,同一次登陸,form表單中的token每次都會變,而cookie中的token不便,django把那個salt存儲在哪裏才能保證驗證經過呢。直到看到源碼。服務器

def _compare_salted_tokens(request_csrf_token, csrf_token): # Assume both arguments are sanitized -- that is, strings of # length CSRF_TOKEN_LENGTH, all CSRF_ALLOWED_CHARS. return constant_time_compare( _unsalt_cipher_token(request_csrf_token), _unsalt_cipher_token(csrf_token), ) def _unsalt_cipher_token(token): """ Given a token (assumed to be a string of CSRF_ALLOWED_CHARS, of length CSRF_TOKEN_LENGTH, and that its first half is a salt), use it to decrypt the second half to produce the original secret. """ salt = token[:CSRF_SECRET_LENGTH] token = token[CSRF_SECRET_LENGTH:] chars = CSRF_ALLOWED_CHARS pairs = zip((chars.index(x) for x in token), (chars.index(x) for x in salt)) secret = ''.join(chars[x - y] for x, y in pairs) # Note negative values are ok return secret 

token字符串的前32位是salt, 後面是加密後的token, 經過salt能解密出惟一的secret。
django會驗證表單中的token和cookie中token是否能解出一樣的secret,secret同樣則本次請求合法。
一樣也不難解釋,爲何ajax請求時,須要從cookie中拿取token添加到請求頭中。cookie

網上有很多關於django csrf token驗證原理的文章都是錯的,是由於他們根本不知道csrf-token的結構組成,我也是卡在第三條評論那.而後看了官方文檔,和CsrfViewMiddleware中間件源碼而後才恍然大悟。加密

做者:鄒黴黴 連接:https://www.jianshu.com/p/7fbb60001018 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
相關文章
相關標籤/搜索