解决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和Ruby中each循环引用变量问题(一个隐秘BUG?)
Jun 04 Python
Python安装Imaging报错:The _imaging C module is not installed问题解决方法
Aug 22 Python
深入理解python对json的操作总结
Jan 05 Python
为什么选择python编程语言入门黑客攻防 给你几个理由!
Feb 02 Python
浅谈配置OpenCV3 + Python3的简易方法(macOS)
Apr 02 Python
Python SQL查询并生成json文件操作示例
Aug 17 Python
Python模拟自动存取款机的查询、存取款、修改密码等操作
Sep 02 Python
python调用支付宝支付接口流程
Aug 15 Python
wxpython多线程防假死与线程间传递消息实例详解
Dec 13 Python
python网络编程socket实现服务端、客户端操作详解
Mar 24 Python
vscode+PyQt5安装详解步骤
Aug 12 Python
将不规则的Python多维数组拉平到一维的方法实现
Jan 11 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 实现类似js中alert() 提示框
2015/03/18 PHP
PHP文件上传类实例详解
2016/04/08 PHP
php实现将数据做成json的格式给前端使用
2018/08/21 PHP
JavaScript中的this关键字介绍与使用实例
2013/06/21 Javascript
javascript:void(0)的问题使用探讨
2014/04/10 Javascript
使用jquery+CSS3实现仿windows10开始菜单的下拉导航菜单特效
2015/09/24 Javascript
JavaScript中获取Radio被选中的值
2015/11/11 Javascript
全面解析Bootstrap图片轮播效果
2015/12/03 Javascript
基于JavaScript实现表单密码的隐藏和显示出来
2016/03/02 Javascript
深入浅析knockout源码分析之订阅
2016/07/12 Javascript
BootStrap实现带有增删改查功能的表格(DEMO详解)
2016/10/26 Javascript
使用smartupload组件实现jsp+jdbc上传下载文件实例解析
2017/01/05 Javascript
一次围绕setTimeout的前端面试经验分享
2017/06/15 Javascript
layui--select使用以及下拉框实现键盘选择的例子
2019/09/24 Javascript
Python入门篇之列表和元组
2014/10/17 Python
Python通过select实现异步IO的方法
2015/06/04 Python
简单介绍Python的Django框架加载模版的方式
2015/07/20 Python
Python黑魔法Descriptor描述符的实例解析
2016/06/02 Python
使用python验证代理ip是否可用的实现方法
2018/07/25 Python
PyQt QListWidget修改列表项item的行高方法
2019/06/20 Python
如何使用Flask-Migrate拓展数据库表结构
2019/07/24 Python
python 数据生成excel导出(xlwt,wlsxwrite)代码实例
2019/08/23 Python
Python3和pyqt5实现控件数据动态显示方式
2019/12/13 Python
使用pyqt5 tablewidget 单元格设置正则表达式
2019/12/13 Python
详解python 降级到3.6终极解决方案
2020/02/06 Python
Python re正则表达式元字符分组()用法分享
2020/02/10 Python
Python3运算符常见用法分析
2020/02/14 Python
python matplotlib.pyplot.plot()参数用法
2020/04/14 Python
Python调用OpenCV实现图像平滑代码实例
2020/06/19 Python
Virtualenv 搭建 Py项目运行环境的教程详解
2020/06/22 Python
StubHub智利:购买和出售您的门票
2016/11/23 全球购物
科茨沃尔德家居商店:Scotts of Stow
2018/06/29 全球购物
品牌推广活动策划方案
2014/08/19 职场文书
学习nginx基础知识
2021/09/04 Servers
Pandas实现DataFrame的简单运算、统计与排序
2022/03/31 Python
MySQL分布式恢复进阶
2022/07/23 MySQL