环境

Window 7

Python2.7

Django1.4.1

sqlite3

问题

在使用Django搭建好测试环境后,写了一个提交POST表单提交留言的测试页面。

如图:

填写表单,点击“提交留言”按钮提交到服务器,却出现

Forbidden (403)

CSRF verification failed. Request aborted.

由于之前使用GET方式提交表单内容测试均正常,就以为这个问题估计是配置问题没细看后边的帮助提示直接在网上搜索解决方案。

一搜索发现相关网页很多,看来大家都遇到过这个问题,想着应该很快能解决。

解决方案1:失败

在settings.py的MIDDLEWARE_CLASSES加入

'django.middleware.csrf.CsrfResponseMiddleware',

最终settings.py MIDDLEWARE_CLASSES 配置部分的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    # add
    'django.middleware.csrf.CsrfResponseMiddleware',
    # add end
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

保存,重新加载http://127.0.0.1/comment/add页面提交留言测试。

但在打开页面时出现500错误

赶紧看了一下控制台,发现如下错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Traceback (most recent call last):
  File "D:\Python27\lib\wsgiref\handlers.py", line 85, in run
    self.result = application(self.environ, self.start_response)
  File "D:\Python27\lib\site-packages\django\contrib\staticfiles\handlers.py", l
ine 67, in __call__
    return self.application(environ, start_response)
  File "D:\Python27\lib\site-packages\django\core\handlers\wsgi.py", line 219, i
n __call__
    self.load_middleware()
  File "D:\Python27\lib\site-packages\django\core\handlers\base.py", line 51, in
 load_middleware
    raise exceptions.ImproperlyConfigured('Middleware module "%s" does not defin
e a "%s" class' % (mw_module, mw_classname))
ImproperlyConfigured: Middleware module "django.middleware.csrf" does not define
 a "CsrfResponseMiddleware" class
[12/Sep/2012 11:00:35] "GET /comment/add/ HTTP/1.1" 500 59

大致的意思是我刚才在settings.py的MIDDLEWARE_CLASSES内添加的

'django.middleware.csrf.CsrfResponseMiddleware',

这个模块找不到,当时就有点郁闷了。网上一大堆都说是添加这个模块解决问题的,现在我本机上添加这个模块以后却提示没有找到模块?

为此,我重新把Django重新安装了一遍还是提示找不到模块。我只好到官网去看看手册,才发现Django新版已去掉这个模块。而我的Django正好是最新版本1.4只好放弃这个方案!

解决方案2:失败

在视图里使用@csrf_protect修饰

于是我在views.py文件里的add函数前加了@csrf_protect修饰符,如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Create your views here.
# coding=utf-8
from django.shortcuts import render_to_response
import datetime
 
@csrf_protect
def add(request):
    dict={}
    if request.method=="POST":
        comment=request.POST.get('comment','')
        submit_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        dict.setdefault('comment',comment)
        dict.setdefault('submit_time',submit_time)
    return render_to_response("comment/add.html",dict)

打开留言页面发现又有一个错误提示

NameError at /comment/add/

name 'csrf_protect' is not defined

提示找不到我刚才添加的修饰符@csrf_protect,应该是没有导入相关模块的问题,于是在我的视图views.py头部添加了一句代码导入相关模块

from django.views.decorators.csrf import csrf_protect

保存文件,重新打开网页,错误已清除。心中一阵大喜,以为OK了。谁知提交留言以后还是提示

Forbidden (403)

CSRF verification failed. Request aborted.

有点急了,只好继续搜索其它解决方案

解决方案3:失败

在模板页的from表单标签内添加{% csrf_token %}

添加以后的代码如下

重新打开页面测试,依旧提示:

Forbidden (403)

CSRF verification failed. Request aborted.

有点火大了!

解决方案4:成功

一番折腾不能解决问题,于是只好冷静的查看错误页面的提示帮助。

第一个提示表示浏览器要开启cookie,我的是IE9浏览器,毋庸置疑默认是开启的。

第三个与第四个方案我都已测试过,唯独第二个方案我没有仔细研究。问题会不会在哪里呢?于是到官网文档寻找

The view function uses RequestContext for the template, instead of Context.

这句英文大致的意思是要在视图里使用RequestContext这个方法,最终在官网文档找到了以下解决方案

在return render_to_response函数里加入context_instance=RequestContext(request),代码如下:

return render_to_response("comment/add.html",dict,context_instance=RequestContext(request))

重新运行网页,又提示新的错误

NameError at /comment/add/

global name 'RequestContext' is not defined

提示找不到RequestContext,估计是我没有导入RequestContext模块,于是在把

from django.shortcuts import render_to_response

改写成

from django.shortcuts import render_to_response,RequestContext

视图整体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Create your views here.
# coding=utf-8
from django.shortcuts import render_to_response, RequestContext
import datetime
from django.views.decorators.csrf import csrf_protect
 
@csrf_protect
def add(request):
    dict={}
    if request.method=="POST":
        comment=request.POST.get('comment','')
        submit_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        dict.setdefault('comment',comment)
        dict.setdefault('submit_time',submit_time)
    return render_to_response("comment/add.html",dict,context_instance=RequestContext(request))

重新运行网页正常,提交留言终于成功了

回顾优化

虽然折腾了半天才解决,但还是感觉有点糊里糊涂的。根据之前报错最后一条提示信息

If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.

大致意思是如果settings.py的MIDDLEWARE_CLASSES里不开启CsrfViewMiddleware那么就必须要在视图里使用@csrf_protect模块修饰方法。我看看MIDDLEWARE_CLASSES里的设置,代码如下:

1
2
3
4
5
6
7
8
9
MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

默认我的MIDDLEWARE_CLASSES已经给我开启了CsrfViewMiddleware这个模块。按照提示帮助,我可以把视图views.py里的修饰模块去掉应该也可以,于是注释了@csrf_protect修饰符与包含模块语句,最终代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Create your views here.
# coding=utf-8
from django.shortcuts import render_to_response, RequestContext
import datetime
# from django.views.decorators.csrf import csrf_protect
 
# @csrf_protect
def add(request):
    dict={}
    if request.method=="POST":
        comment=request.POST.get('comment','')
        submit_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        dict.setdefault('comment',comment)
        dict.setdefault('submit_time',submit_time)
    return render_to_response("comment/add.html",dict,context_instance=RequestContext(request))

测试成功!

什么是CSRF

问题是解决了,但我不禁回想为什么在Django里提交POST表单要配置那么麻烦(其实也不麻烦,但对新手来说就不一样了),于是搜索关键字看看,得知它是一种跨站请求伪造,黑客可以利用这个攻击站点。 而Django里的使用这个机制就是防止CSRF模式攻击,原理大致是当你打开页面的时候产生一个csrftokey种下cookie,然后当你提交表单 时会把本地cookie里的csrftokey值给提交服务器,服务器判断只有有效的csrftokey值才处理请求。

既然这样,我就查看了一下cookie信息,发现果真种了一个csrftokey值

右键HTML页面查看源代码,发现{% csrf_token %}位置替换成了一个input隐藏值

input隐藏标签值与cookie里的csrftoken值一致。

于是我做了一个测试,在from表单里把{% csrftoken %}标签直接替换成如上图的input标签,name与value保持一致,提交留言的时候服务器正常处理,测试成功。

不使用CSRF验证

Django提供了POST表单使用CSRF验证功能,感觉还是挺不错的。但在Django里能不能像普通的Form表单一样不使用CSRF验证功能呢?答案是肯定可以的。

1、我在settings.py的MIDDLEWARE_CLASSES把'django.middleware.csrf.CsrfViewMiddleware'注释

2、移出FROM表单里的{% csrf_token %}标记

3、不导入RequestContext模块,并把render_to_response()里的context_instance=RequestContext(request)去掉

重新运行网页测试提交留言正常。至此,应该可以判断出上边1步骤里的'django.middleware.csrf.CsrfViewMiddleware'语句开启了CSRF验证功能,默认是开启的,注释以后就关闭CSRF验证POST表单提交功能了。

支持一下(195)
 

python, Django csrf token的问题的更多相关文章

  1. django CSRF token missing or incorrect

    django 异步请求时提示403 按照一般情况权限问题,python文件没有问题,仔细看了下response里有一句 CSRF token missing or incorrect.这个肯定是因为安 ...

  2. pythonのdjango CSRF简单使用

    一.简介 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成.而对于django中设置防跨站请求伪造功 ...

  3. django csrf token添加

    #views.py from django.shortcuts import render_to_response, RequestContext from django.views.decorato ...

  4. Python - Django - CSRF

    CSRF 攻击: 把 settings.py 中的 csrf 注释掉 正规网站: 创建修改密码页面 password.html: <!DOCTYPE html> <html lang ...

  5. Django中csrf token验证原理

    我多年没维护的博客园,有一篇初学Django时的笔记,记录了关于django-csrftoekn使用笔记,当时几乎是照抄官网的使用示例,后来工作全是用的flask.博客园也没有维护.直到我的博客收到了 ...

  6. Django后台post请求中的csrf token

    使用Requests库操作自己的Django站点,post登陆admin页面返回403,serverlog显示csrf token not set. csrf token是get登陆页面时服务器放在c ...

  7. django rest framework csrf failed csrf token missing or incorrect

    django rest framework csrf failed csrf token missing or incorrect REST_FRAMEWORK = { 'DEFAULT_AUTHEN ...

  8. 对于 前端请求Django 后端服务出现403 Forbidden (CSRF token missing or incorrect.) 问题的解析

    Django中使用ajax post向後臺傳送資料時403 Forbidden (CSRF token missing or incorrect.):的解決辦法 在Django中使用ajax post ...

  9. 使用Ajax (put delete ) django原生CBV 出现csrf token解决办法

    原因 django原生CBV中对于 Ajax put 或 delete 请求进行封装时,会把请求数据放在 request.body里, 所以获取不到csrf token 方式一: 关闭csrf 中间件 ...

随机推荐

  1. Windows 10 子系统 Ubuntu 中安装 FastAdmin

    Windows 10 子系统 Ubuntu 中安装 FastAdmin 打开 Windows 10 子系统 安装 Ubuntu 修改安装源为阿里的 %LOCALAPPDATA%\Packages\Ca ...

  2. hadoop yarn 知识点

    yarn 简介: Yarn是一个分布式的资源管理系统,用以提高分布式的集群环境下的资源利用率,这些资源包括内存.IO.网络.磁盘等.其产生的原因是为了解决原MapReduce框架的不足.最初MapRe ...

  3. Mac 平台安装 Android Studio 集成 Android SDK

    最近写个小工具,给周边一些朋友用用(类似任务执行),一开始 任务执行用Python写的,部署在云端,有一些局限(资金开销):现准备写一个任务端,需要用到的人直接装个客户端就行,于是准备写个客户端版本的 ...

  4. Thinkphp自动验证规则

    其实说白了,这篇文章就是转给自己看的,省的下次用的时候满网络找了.有需要的同学也可以看看.自动验证是非常有用的一个技术.平常的验证基本就是,用户名是否为空,用户名是否重复,密码,重复密码是否一致.官方 ...

  5. AI(四): 微信与luis结合(下)

    LUIS(Language Understanding Intelligent Services)是微软新近推出了的的语义理解服务,可以方便用户进行API调用,创建自己场景的语义理解服务,网址为 ht ...

  6. BASIC-21_蓝桥杯_Sine之舞

    思路: 先根据例子找出规律,列出递归要打印的数据; 示例代码: #include <stdio.h> int n = 0; void dg(int x){ int i = 0; if (x ...

  7. 术语-服务:PaaS

    ylbtech-术语-服务:PaaS PaaS是Platform-as-a-Service的缩写,意思是平台即服务. 把服务器平台作为一种服务提供的商业模式.通过网络进行程序提供的服务称之为SaaS( ...

  8. 夜神模拟器+seleinm抓取手机app(参考资料集合)

    目前准备开始实现这个技术,将看起来还算可靠的参考链接粘贴如下: http://www.cnblogs.com/puresoul/p/4597211.html https://www.cnblogs.c ...

  9. C# winfrom ComboBox 调整下拉菜单的高度

    1.设置属性 // 1.属性设置 DrawMode ->OwnerDrawVariable this.cboBoxPostID.DrawMode = System.Windows.Forms.D ...

  10. RESTful Java client with Apache HttpClient / URL /Jersey client

    JSON example with Jersey + Jackson Jersey client examples RESTful Java client with RESTEasy client f ...