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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
最新文章
- docker 初探之简单安装 ----Windows10
- [delphi]indy idhttp post方法
- [python学习笔记]Day1
- Javascript对象赋值操作
- 【OpenGL】交互式三次 Bezier 曲线
- PostgreSQL Replication之第十一章 使用Skytools(5)
- Moses创建一个翻译系统的基本过程记录,以后会按照每个过程详细说明,并给出每个步骤的参数说明
- SQL Server 2008中新增的变更数据捕获(CDC)和更改跟踪
- 1710: [Usaco2007 Open]Cheappal 廉价回文
- mysql 查询表
- SeekBar.OnSeekBarChangeListener解析
- python基础教程第2章——列表与元组笔记
- 孙陪你,了解它的力量——unity3d流程暂停
- 工作日志(DJ)
- reshape2 数据操作 数据融合 (melt)
- STM32 对内部FLASH读写接口函数(转)
- 直方图均衡化及matlab实现
- 什么是POE交换机?
- webpack中插件 prerender-spa-plugin 来进行SEO优化(二十四)
- Tomcat日志设定
热门文章
- ubuntu18.04 编译fortran出现 ‘没有f951这个文件’处理
- c++ char*和wchar*互相转换(转)
- 风变编程笔记(二)-Python爬虫精进
- SpringBoot整合WEB开发--(七)注册拦截器
- Jmeter-Badboy检查点和参数化
- Chrome 提标 您的浏览器限制了第三方Cookie...解决方法
- 2020牛客竞赛 DP F	碎碎念
- 一点点学习PS--实战五
- C语言-条件编译使用分析
- IntelliJ IDEA 2017.3尚硅谷-----模板