Django中csrf token验证原理
我多年没维护的博客园,有一篇初学Django时的笔记,记录了关于django-csrftoekn使用笔记,当时几乎是照抄官网的使用示例,后来工作全是用的flask。博客园也没有维护。直到我的博客收到了如下评论,确实把我给问倒了,而且我也仔细研究了这个问题。
1. Django是怎么验证csrfmiddlewaretoken合法性的?
2. 每次刷新页面的时候<input>中的csrf的value都会更新,每次重复登录的时候cookie的csrf令牌都会刷新,那么这两个csrf-token有什么区别?

CSRF(Cross Site Request Forgery protection),中文简称跨站请求伪造。
django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,把这个 token 放在 cookie 里。然后每次 POST 请求都会带上这个 token,
这样就能避免被 CSRF 攻击。
这样子看起来似乎没毛病,但是评论中的第三个问题,每次刷新页面,form表单中的token都会刷新,而cookie中的token却只在每次登录时刷新。我对csrftoken的验证方式起了疑问,后来看了一段官方文档的解释。
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.
官方文档中说到,检验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添加到请求头中。
网上有不少关于django csrf token验证原理的文章都是错的,是因为他们根本不知道csrf-token的结构组成,我也是卡在第三条评论那.然后看了官方文档,和CsrfViewMiddleware中间件源码然后才恍然大悟。
作者:邹霉霉
链接:https://www.jianshu.com/p/7fbb60001018
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
Django中csrf token验证原理的更多相关文章
- Django 中CSRF中间件 'django.middleware.csrf.CsrfViewMiddleware',
1.Django中CSRF中间件的工作原理及form表单提交需要添加{% csrf_token %}防止出现403错误 CSRF # 表示django全局发送post请求均需要字符串验证功能:防止跨站 ...
- Django restframework之Token验证的缺陷及jwt的简单使用
一.主要缺陷: 1.Token验证是放在一张表中,即authtoken_token中,key没有失效时间,永久有效,一旦泄露,后果不可想象,安全性极差. 2.不利于分布式部署或多个系统使用一套验证,a ...
- CSRF token的原理
参考: http://www.cnblogs.com/zhaof/p/6281482.html 简介 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.cs ...
- Django中csrf错误
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站 ...
- webapi中使用token验证(JWT验证)
本文介绍如何在webapi中使用JWT验证 准备 安装JWT安装包 System.IdentityModel.Tokens.Jwt 你的前端api登录请求的方法,参考 axios.get(" ...
- c# asp.net 中使用token验证
基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息.这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提 ...
- Vue中实现token验证
前后端流程分析 前端页面进行登录操作,将用户名和密码发给服务器 服务器进行校验,通过后生成token,包含信息有密匙.uid.过期时间等,然后返回给前端 前端将token保存在本地(建议在localS ...
- Swagger中添加Token验证
1.该连接链接到api中基本的swagge功能:http://www.cnblogs.com/hhhh2010/p/5234016.html 2.在swagger中使用验证(这里使用密码验证模式)ht ...
- Django中使用geetest验证
一.geetest的使用方法 首先需要在setting中配置好文件 GEE_TEST = { "gee_test_access_id": "37ca5631edd1e88 ...
随机推荐
- contenteditable兼容问题
正常情况下用contenteditable,IE下有兼容性问题需要将个别字母变成大写的contentEditable. 获取contenteditable的内容 对html进行处理 兼容 chrome ...
- c++实现服务器和多个客户端的实时群聊通信
我们通过TCP/IP来实现多人聊天室,如果租一个服务器我们就可以实现全网的多人聊天室(不懂tcp/ip的点进来https://www.cnblogs.com/yskn/p/9335608.html)! ...
- 【转载】Stanford CoreNLP Typed Dependencies
总结自Stanford typed dependencies manual 原文链接:http://www.jianshu.com/p/5c461cf096c4 依存关系描述句子中词与词之间的各种语法 ...
- 怎么去掉zencart模板网址后面的zenid=数字这个东西
搜索引擎优化后第一次进入商店网址URL后面会出现zenid=XXXX 如:http://afish.cnblogs.com/zencart-zenid.html?zenid=tbisz675099db ...
- [易学易懂系列|rustlang语言|零基础|快速入门|(21)|智能指针]
[易学易懂系列|rustlang语言|零基础|快速入门|(21)|智能指针] 实用知识 智能指针 我们今天来讲讲Rust中的智能指针. 什么是指针? 在Rust,指针(普通指针),就是保存内存地址的值 ...
- 关于log4j的配置文件
因为要在spring中添加Mongodb,在网上查阅资料的时候我发现有人在web.xml中添加如下代码: <context-param> <param-name>l ...
- C++ Primer 第 5 版 习题参考答案
从 5 月初 - 8 月 16 日,每天基本都在啃 C++ 的语法.起初直接看C++ Primer 中文版(第 5 版),发现后边的章节看着很吃力.所以就转而看了清华大学郑莉老师和李超老师的视频C++ ...
- The Preliminary Contest for ICPC Asia Nanchang 2019 E. Magic Master
题目:https://nanti.jisuanke.com/t/41352 思路:约瑟夫环 由题意得第k张牌即求 k 为 第几个 报数为m+1 的单位 用队列模拟即可 #include<bits ...
- Gym - 101173H Hangar Hurdles (kruskal重构树/最小生成树+LCA)
题目大意:给出一个n*n的矩阵,有一些点是障碍,给出Q组询问,每组询问求两点间能通过的最大正方形宽度. 首先需要求出以每个点(i,j)为中心的最大正方形宽度mxl[i][j],可以用二维前缀和+二分或 ...
- cookie和session django中间件
目录 一.cookie和session 1. 为什么要有cookie和session 二.cookie 1. 什么是cookie 2. django中关于cookie的使用 (1)后端设置cookie ...