Environment
Window 7
Python2.7
Django1.4.1
Sqlite3
Problem
After using Django to build a test environment, write a test page that submits a post form submission message.
Fill out the form, click the "Submit Message" button to submit to the server, but appears
Forbidden (403)
CSRF verification failed. Request aborted.
Since the previous use of the Get method to submit the form content test is normal, think that this problem is estimated to be a configuration problem without a closer look behind the help tips to search the solution directly on the Internet.
A search found a lot of related pages, it seems that we have encountered this problem, thinking that it should be resolved soon.
Solution 1: Failure
Join in Settings.py's middleware_classes
' Django.middleware.csrf.CsrfResponseMiddleware ',
The code for the final settings.py middleware_classes configuration section is as follows:
123456789101112 |
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‘,
)
|
Save, Reload Http://127.0.0.1/comment/add page submit message test.
However, a 500 error occurred while opening the page
Quickly looked at the console, found the following error
12345678910111213141516 |
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
|
Roughly, I just added it in Settings.py's middleware_classes.
' Django.middleware.csrf.CsrfResponseMiddleware ',
This module can not find, then a bit depressed. Online a lot of said to add this module to solve the problem, and now I add this module on the machine after the prompt did not find the module?
To do this, I re-installed Django again or I was prompted not to find the module. I had to go to the official website to see the manual, only to find that the Django version has removed this module. And my Django happens to be the latest version 1.4 just give up this solution!
Solution 2: Failure
Using @csrf_protect adornments in views
So I added the @csrf_protect modifier to the Add function in the views.py file, with the following code:
1234567891011121314 |
# 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
)
|
Open the Message page found another error message
Nameerror at/comment/add/
Name ' Csrf_protect ' is not defined
Hint can not find the modifier I just added @csrf_protect, should be not imported related module problem, so in my view views.py header added a code import related module
From DJANGO.VIEWS.DECORATORS.CSRF import Csrf_protect
Save the file, reopen the webpage, and the error is cleared. Heart a burst of exultation, thought OK. Who knows after submitting the message or prompt
Forbidden (403)
CSRF verification failed. Request aborted.
It's a bit of a hurry. Search Other Solutions
Solution 3: Failure
Add {% Csrf_token%} to the From Form tab of the template page
Add the following code as follows
Re-open the page test, still prompt:
Forbidden (403)
CSRF verification failed. Request aborted.
There's a big ignition!
Solution 4: Success
A toss can not solve the problem, so have to calmly view the error page tips help.
The first hint indicates that the browser is going to turn on the cookie, my IE9 browser, which is no doubt open by default.
The third and fourth scenarios I have tested, but the second one I did not study carefully. Will the problem be where? Then go to the official website document search
The view function uses RequestContext for the template, instead of the Context.
This English general meaning is to use RequestContext this method in the view, finally found the following solution on the official website document
Add Context_instance=requestcontext (Request) to the return Render_to_response function with the following code:
Return Render_to_response ("comment/add.html", Dict,context_instance=requestcontext (Request))
Re-run the webpage and prompt for new errors
Nameerror at/comment/add/
Global name ' RequestContext ' is not defined
RequestContext, it is estimated that I did not import the RequestContext module, so in the
From django.shortcuts import Render_to_response
Rewrite into
From django.shortcuts import Render_to_response,requestcontext
The overall view code is as follows:
123456789101112131415 |
# 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))
|
Re-run the webpage is OK, submit the message finally succeeded
Review optimization
Although the toss for a long while to solve, but still feel a little confused. According to the last message of the previous error message
If you is not using the Csrfviewmiddleware and then you must use Csrf_protect on any of the Csrf_token template tag, As well as those that accept the POST data.
The general meaning is that if the settings.py middleware_classes does not open csrfviewmiddleware then it is necessary to use the @csrf_protect module decoration method in the view. I look at the settings in Middleware_classes, the code is as follows:
123456789 |
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‘,
)
|
By default my middleware_classes has opened the Csrfviewmiddleware module for me. With the help of the prompts, I can remove the modified module in the view views.py should also be able to, so commented the @csrf_protect modifier and contains the module statement, the final code is as follows:
123456789101112131415 |
# 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))
|
Test success!
What is CSRF
The problem is solved, but I can't help but recall why submitting a post form in Django is so cumbersome (it's not a hassle, but it's not the same for newbies), so search the keyword to see that it's a cross-site request forgery that hackers can use to attack the site . And Django's use of this mechanism is to prevent CSRF mode attack, basically, when you open the page to generate a Csrftokey cookie, and then when you submit the form will be the local cookie Csrftokey value to the submission server, The server determines that only valid Csrftokey values are processed for the request.
In that case, I looked at the cookie information and found that a Csrftokey value was actually planted
Right-click the HTML page to view the source code, and find that {% Csrf_token%} is replaced with an input hidden value
Input hides the tag value in accordance with the Csrftoken value in the cookie.
So I made a test, in the from form to replace the {% Csrftoken%} tag directly with the input tag of Chengru, name and value consistent, submit the message when the server normal processing, test success.
Do not use CSRF authentication
Django provides a post form that uses the CSRF verification feature and feels pretty good. But is it possible in Django to not use the CSRF verification function like a normal form form? The answer is certainly yes.
1, I in settings.py's middleware_classes put ' django.middleware.csrf.CsrfViewMiddleware ' annotation
2. Remove the {% Csrf_token%} Mark from the From form
3, do not import RequestContext module, and Render_to_response () in the Context_instance=requestcontext (request) removed
Rerun Web test submission message is OK. At this point, it should be possible to determine the above 1 steps in the ' Django.middleware.csrf.CsrfViewMiddleware ' statement turned on the CSRF authentication function, the default is turned on, the note will be closed after the CSRF verify the Post form submission function.
Reprint to: http://www.qttc.net/201209211.html
Django POST CSRF verification failed. Request Abor