python, Django csrf token的问题

环境

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)

时间: 2024-10-08 22:42:49

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

Django后台post请求中的csrf token

使用Requests库操作自己的Django站点,post登陆admin页面返回403,serverlog显示csrf token not set. csrf token是get登陆页面时服务器放在cookies中返回的. 所以完整的登陆应该是这样的: import requests s = requests.Session() r = s.get("http://serveraddr/admin") s.cookies = r.cookies loginpage = s.post(a

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

原文地址: https://blog.csdn.net/weixin_35993084/article/details/80778921 修改ajax中type方式并设置header,同时对put重新构建数据字典 在对views中的方法进行类对象封装时,发现django并不支持像post和get一样将数据封装. 由于网页端无法设置method方法,在用postman和ajax开启pycharm对接口进行debug测试时发现:提交数据后并没有进入代码逻辑. 查阅资料得知,django支持put和d

python django mysql 遇到的问题小结

最近遇到的问题小结: 1.django 工程内不要有与项目名称相同的文件.会导致无法import settings.py文件. 2.django 的 csrf 问题,当发送post请求时,会要求同时发送csrf token,是为了防止跨站请求伪造. 具体使用方法见官方文档. http://docs.djangoproject.com/en/dev/ref/contrib/csrf/ 但我的情况是我用python发送post请求来测试我的服务,没有这个csrf token的话,django就只会返

python Django之Ajax

python Django之Ajax AJAX,Asynchronous JavaScript and XML (异步的JavaScript和XML),一种创建交互式网页应用的网页开发技术方案. 异步的JavaScript:使用 [JavaScript语言] 以及 相关[浏览器提供类库] 的功能向服务端发送请求,当服务端处理完请求之后,[自动执行某个JavaScript的回调函数].PS:以上请求和响应的整个过程是[偷偷]进行的,页面上无任何感知. XMLXML是一种标记语言,是Ajax在和后台

"CSRF token missing or incorrect."的解决方法.

现象: Forbidden (403)CSRF verification failed. Request aborted.HelpReason given for failure:CSRF token missing or incorrect. In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been use

[python] python django web 开发 —— 15分钟送到会用(只能送你到这了)

1.安装python环境 1.1 安装python包管理器: wget https://bootstrap.pypa.io/get-pip.py sudo python get-pip.py ? 1.2 安装python虚拟环境virtualenv virtualenvwrapper 首先说明下为什么要装这两个包: First, it's important to understand that a virtual environment is a special tool used to ke

Django CSRF与auth模块

目录 Django CSRF与auth模块 CSRF CSRF相关装饰器 auth模块 扩展默认的auth_user表 Django CSRF与auth模块 CSRF FORM表单中怎么通过CSRF校验 只需要在form表单中写一个 {% csrf_token %} ajax通过asrf校验有三种方法 $.ajax({ url:'', type:'post', {#data:{'username':'yang'},#} //第一种方式 自己手动获取 {#data:{'username':'yan

用python+django+twistd 开发一个属于自己的运维系统

开源的运维系统不少,比如nagios.zabbix.cati等等,但是遇到自己个性化的运维需求的时候,总是显的力不从心!最近在学习python,所以就考虑用python+django+twisted来定做一个完全个性化的运维系统. 运维系统有几个主要的功能:监控.分析.报警.更甚者直接根据分析的结果进行反应操作.而以上几点通过上述的框架可以比较容易的实现. 下面上图说明: 使用freemind整理了下思路: 下面是一些代码段,完整的代码下载见文档底部: Server: #!/usr/bin/en

python+django 更改了urls.py 之后runserver报错的解决办法

新手学python+django时,更改了urls.py 为: from django.conf.urls import patterns, include, urlfrom django.contrib import adminadmin.autodiscover() urlpatterns = patterns('',    # Examples:    # url(r'^$', 'mysite.views.home', name='home'),    # url(r'^blog/', i