Django提交表單時遇到403錯誤:CSRF verification failed
阿新 • • 發佈:2019-02-20
在學習Django框架提交表單時,遇到了403錯誤,詳細資訊如下:
根據提示依次check一遍:Forbidden (403) CSRF verification failed. Request aborted. You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties. If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests. Help Reason given for failure: CSRF cookie not set. In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure: 1. Your browser is accepting cookies. 2. The view function passes a request to the template's render method. 3. In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL. 4. 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. 5. The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login.
1. 我的瀏覽器是開啟了cookie的,沒毛病;
2. 我的view.py中的程式碼是這樣的:
#coding=utf-8 from django.shortcuts import render, render_to_response #表單 class UserForm(forms.Form): username = forms.CharField(label='使用者名稱',max_length=20) password = forms.CharField(label='密碼',widget=forms.PasswordInput()) def register(request): if request.method == 'POST': uf = UserForm(request.POST) if uf.is_valid(): #獲得表單資料 username = uf.cleaned_data['username'] password = uf.cleaned_data['password'] #新增到資料庫 User.objects.create(username= username,password=password) return HttpResponse('Register success!!') else: return HttpResponse('Register failed!!') else: uf = UserForm() return render_to_response('register.html', context=RequestContext(request, {'uf':uf}))
這段程式碼是從網上拷貝的,這裡也確實使用了RequestContext,並且將request傳給RequestContext了,好像也沒什麼問題。
3. 我的模板內容是這樣的:
模板中也確實用了"{% csrf_token %}",好像也沒什麼問題。<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>註冊</title> </head> <body> <h1>註冊頁面:</h1> <form method="post" enctype="multipart/form-data"> {% csrf_token %} {{uf.as_p}} <input type="submit" value = "註冊" /> </form> <br> <a href="/login/">登陸</a> </body> </html>
4. 中介軟體CsrfViewMiddleware在工程建立的就預設加入了,也沒毛病。
5. 第一次提交表單的時候就出現了403錯誤,都沒有後退的機會,該項也可以忽略。
又額外查看了兩點:
1. 後臺伺服器打印出如下日誌:
UserWarning: A {% csrf_token %} was used in a template, but the context did not provide the value. This is usually caused by not using RequestContext.
2. 檢視瀏覽器的cookie
我是用的chrome瀏覽器,安裝外掛Web Developer,可以看到該網頁確實沒有設定任何cookie。
可以看到頁面的cookie沒有設定成功,而設定cookie在check列表的第2項完成,本機安裝的Django是1.10版本,而拷貝的這段程式碼是在1.10之前的版本下執行的,猜測可能是方法render_to_response導致的,改用render方法:
def register(request):
if request.method == 'POST':
uf = UserForm(request.POST)
if uf.is_valid():
#獲得表單資料
username = uf.cleaned_data['username']
password = uf.cleaned_data['password']
#新增到資料庫
User.objects.create(username= username,password=password)
return HttpResponse('Register success!!')
else:
return HttpResponse('Register failed!!')
else:
uf = UserForm()
return render(request, 'register.html', Context({'uf':uf}))
結果可以正常工作了,通過Web Developer可以看到cookie "csrftoken"被頁設定成功了: