热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python,Djangocsrftoken的问题

环境Window7Python2.7Django1.4.1sqlite3问题在使用Django搭建好测试环境后,写了一个提交POST表单提交留言的测试页面。

环境

Window 7

Python2.7

Django1.4.1

sqlite3

问题

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

如图:

Django表单

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

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错误

Django表单

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

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 %}

添加以后的代码如下

Django表单

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

Forbidden (403)

CSRF verification failed. Request aborted.

有点火大了!

解决方案4:成功

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

Django表单

第一个提示表示浏览器要开启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))

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

Django表单

回顾优化

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

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值

Django表单

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

Django表单

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)
 

推荐阅读
  • Django框架进阶教程:掌握Ajax请求的基础知识与应用技巧
    本教程深入探讨了Django框架中Ajax请求的核心概念与实用技巧,帮助开发者掌握异步数据交互的方法,提升Web应用的响应速度和用户体验。通过实例解析,详细介绍了如何在Django项目中高效实现Ajax请求,涵盖从基础配置到复杂场景的应用。 ... [详细]
  • 中间件的概念中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实 ... [详细]
  • 本课程详细介绍了如何使用Python Flask框架从零开始构建鱼书应用,涵盖高级编程技巧和实战项目。通过视频教学,学员将学习到Flask的高效用法,包括数据库事务处理和书籍交易模型的实现。特别感谢AI资源网提供的课程下载支持。 ... [详细]
  • Django项目中配置媒体文件路径的详细步骤与最佳实践
    在Django项目中配置媒体文件路径的详细步骤包括:首先,创建一个新的应用(如 `app02`),然后在 `settings.py` 文件中配置媒体文件的存储路径。具体来说,需要导入 `os` 模块,并使用 `os.path.join` 方法来指定媒体文件的保存目录。此外,建议在开发和生产环境中分别设置不同的媒体文件路径,以确保项目的灵活性和安全性。为了更好地管理和访问媒体文件,还可以在 `urls.py` 中添加相应的URL配置,以便在开发服务器上直接访问这些文件。 ... [详细]
  • FBV代表func,也就是函数。CBV代表class,也就是类应用场景:登录验证.FBV写法:deflogin(request):dic{tag:N ... [详细]
  • 我是Django的初学者。现在,我正在使用API​​。我面临一个问题。我无法在 ... [详细]
  • python flask面试题_Python面试的50个经典问答,助你从容通过面试(下)
    26)Python中的局部变量和全局变量的使用规则是什么?局部变量:仅可在某个对象或函数内部使用,无法被其他对象或函数所引 ... [详细]
  • Python学习:环境配置与安装指南
    Python作为一种跨平台的编程语言,适用于Windows、Linux和macOS等多种操作系统。为了确保本地已成功安装Python,用户可以通过终端或命令行界面输入`python`或`python3`命令进行验证。此外,建议使用虚拟环境管理工具如`venv`或`conda`,以便更好地隔离不同项目依赖,提高开发效率。 ... [详细]
  • 在《孙鑫VC++讲座笔记第三讲》中,深入探讨了MFC应用程序的架构,并详细解析了SDI程序的流程图。AfxWinMain()函数位于WINMAIN.CPP文件中,其主要职责包括调用AfxWinInit()进行框架初始化,以及通过pApp->InitApplication()执行应用内部的初始化过程。此外,还详细分析了各个关键函数的作用及其在程序启动过程中的具体功能。 ... [详细]
  • 在处理大规模并发请求时,传统的多线程或多进程模型往往无法有效解决性能瓶颈问题。尽管它们在处理小规模任务时能提升效率,但在高并发场景下,系统资源的过度消耗和上下文切换的开销会显著降低整体性能。相比之下,Python 的 `asyncio` 模块通过协程提供了一种轻量级且高效的并发解决方案。本文将深入解析 `asyncio` 模块的原理及其在实际应用中的优化技巧,帮助开发者更好地利用协程技术提升程序性能。 ... [详细]
  • 深入解析 Android Drawable:第六阶段进阶指南 ... [详细]
  • Android目录遍历工具 | AppCrawler自动化测试进阶(第二部分):个性化配置详解
    终于迎来了“足不出户也能为社会贡献力量”的时刻,但有追求的测试工程师绝不会让自己的生活变得乏味。与其在家消磨时光,不如利用这段时间深入研究和提升自己的技术能力,特别是对AppCrawler自动化测试工具的个性化配置进行详细探索。这不仅能够提高测试效率,还能为项目带来更多的价值。 ... [详细]
  • 转自http:jamsa.iteye.comblog160972页面创建页面的基本步骤是创建pages,region,items。PageLayoutRegion的关键属性创建一个 ... [详细]
  • JMeter如何使用MD5加密并且对body进行指纹签名
    前言:接口测试过程中,有时候会遇到需要进行加解密的接口,下面我就来介绍如何针对MD5加密接口测试,并且针对body全部参数进 ... [详细]
  • django示例_介绍信模板前言目前市面上有非常多的模板系统,其中最知名最好用的就是DTL和Jinja2。DTL是DjangoTemplateLanguage三个单词的缩写,也就是 ... [详细]
author-avatar
小白一枚
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有