解决Django提交表单报错:CSRF token missing or incorrect的问题


Posted in Python onMarch 13, 2020

1、在Django提交表单时报错:Django提交表单报错:

CSRF token missing or incorrect

具体报错页面如下:

解决Django提交表单报错:CSRF token missing or incorrect的问题

2、有道词典翻译后如下:

通常,当存在真正的跨站点请求伪造时,或者Django的CSRF机制没有被正确使用时,就会出现这种情况。至于邮递表格,你须确保:

您的浏览器正在接受cookie。

视图函数将一个请求传递给模板的呈现方法。

在模板中,每个POST表单中都有一个{% csrf_token %}模板标记,目标是一个内部URL。

如果您没有使用CsrfViewMiddleware,那么您必须在任何使用csrf_token模板标签的视图以及那些接受POST数据的视图上使用csrf_protect。

该表单有一个有效的CSRF令牌。在登录另一个浏览器选项卡或登录后单击back按钮之后,您可能需要使用表单重新加载页面,因为登录后令牌会旋转。

您将看到这个页面的帮助部分,因为在Django设置文件中有DEBUG = True。将其更改为False,将只显示初始错误消息。

您可以使用CSRF_FAILURE_VIEW设置自定义这个页面。

3、解决办法:

(1)、确定项目底下的settings.py文件,是否存在django.middleware.csrf.CsrfViewMiddleware:

MIDDLEWARE = [
  'django.middleware.security.SecurityMiddleware',
  'django.contrib.sessions.middleware.SessionMiddleware',
  'django.middleware.common.CommonMiddleware',
  'django.middleware.csrf.CsrfViewMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
  'django.contrib.messages.middleware.MessageMiddleware',
  'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

(2)、如果确定settings.py文件有配置了,还是报错,就要在form表单底下加一行代码:

{% csrf_token %}

这样应该就不会报上面错误了,以上内容仅供学习参考,谢谢!

补充知识:Django中csrf token验证原理

我多年没维护的博客园,有一篇初学Django时的笔记,记录了关于django-csrftoekn使用笔记,当时几乎是照抄官网的使用示例,后来工作全是用的flask。博客园也没有维护。直到我的博客收到了如下评论,确实把我给问倒了,而且我也仔细研究了这个问题。

1. Django是怎么验证csrfmiddlewaretoken合法性的?

2. 每次刷新页面的时候<input>中的csrf的value都会更新,每次重复登录的时候cookie的csrf令牌都会刷新,那么这两个csrf-token有什么区别?

解决Django提交表单报错:CSRF token missing or incorrect的问题

image.png
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中间件源码然后才恍然大悟。

以上这篇解决Django提交表单报错:CSRF token missing or incorrect的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python编写生成验证码的脚本的教程
May 04 Python
python对html代码进行escape编码的方法
May 04 Python
python使用PyCharm进行远程开发和调试
Nov 02 Python
Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例
Dec 12 Python
python实现基于SVM手写数字识别功能
May 27 Python
Python cookbook(数据结构与算法)从任意长度的可迭代对象中分解元素操作示例
Feb 13 Python
使用Python搭建虚拟环境的配置方法
Feb 28 Python
Python简单实现两个任意字符串乘积的方法示例
Apr 12 Python
查看Python依赖包及其版本号信息的方法
Aug 13 Python
解决Djang2.0.1中的reverse导入失败的问题
Aug 16 Python
pycharm第三方库安装失败的问题及解决经验分享
May 09 Python
Python内置方法和属性应用:反射和单例(推荐)
Jun 19 Python
python爬虫实现获取下一页代码
Mar 13 #Python
Python3 利用face_recognition实现人脸识别的方法
Mar 13 #Python
在django中使用post方法时,需要增加csrftoken的例子
Mar 13 #Python
python 安装教程之Pycharm安装及配置字体主题,换行,自动更新
Mar 13 #Python
详解用Python进行时间序列预测的7种方法
Mar 13 #Python
django-xadmin根据当前登录用户动态设置表单字段默认值方式
Mar 13 #Python
在django项目中导出数据到excel文件并实现下载的功能
Mar 13 #Python
You might like
PHP 字符串编码截取函数(兼容utf-8和gb2312)
2009/05/02 PHP
php获取汉字首字母的函数
2013/11/07 PHP
Laravel如何实现适合Api的异常处理响应格式
2020/06/14 PHP
Jquery拖拽并简单保存的实现代码
2010/11/28 Javascript
深入浅析JavaScript面向对象和原型函数
2016/02/06 Javascript
Jquery判断form表单数据是否变化
2016/03/30 Javascript
又一枚精彩的弹幕效果jQuery实现
2016/07/25 Javascript
HTML页面定时跳转方法解析(2种任选)
2016/12/22 Javascript
bootstarp modal框居中显示的实现代码
2017/02/18 Javascript
AngularJS2中一种button切换效果的实现方法(二)
2017/03/27 Javascript
AngularJs 延时器、计时器实例代码
2017/09/16 Javascript
Vue实现侧边菜单栏手风琴效果实例代码
2018/05/31 Javascript
详解原生JS回到顶部
2019/03/25 Javascript
Python程序语言快速上手教程
2012/07/18 Python
在Windows8上的搭建Python和Django环境
2014/07/03 Python
python实现的登录和操作开心网脚本分享
2014/07/09 Python
跟老齐学Python之类的细节
2014/10/13 Python
Python利用IPython提高开发效率
2016/08/10 Python
python使用opencv按一定间隔截取视频帧
2018/03/06 Python
使用python3+xlrd解析Excel的实例
2018/05/04 Python
python smtplib模块自动收发邮件功能(一)
2018/05/22 Python
Python flask框架post接口调用示例
2019/07/03 Python
简单了解Django ContentType内置组件
2019/07/23 Python
Python中logger日志模块详解
2020/08/04 Python
Python logging日志库空间不足问题解决
2020/09/14 Python
python Cartopy的基础使用详解
2020/11/01 Python
夏尔巴人登珠峰品牌:Sherpa Adventure Gear
2018/02/08 全球购物
外语系毕业生自荐信范文
2013/12/16 职场文书
学校领导四风问题整改措施思想汇报
2014/10/09 职场文书
2015年乡镇信访工作总结
2015/04/07 职场文书
采购部年度工作总结
2015/08/13 职场文书
祝福语集锦:朋友新店开业祝福语
2019/12/10 职场文书
详解Redis在SpringBoot工程中的综合应用
2021/10/16 Redis
「Manga Time Kirara MAX」2022年5月号封面公开
2022/03/21 日漫
多线程Spring通过@Scheduled实现定时任务
2022/05/25 Java/Android
利用Redis实现点赞功能的示例代码
2022/06/28 Redis