![](/img/trans.png)
[英]Can't submit a post request using Django rest framework (“detail”: “CSRF Failed: CSRF token missing or incorrect.”)
[英]Django rest-api: Postman can't see CSRF token
我在ubuntu
服務器上使用django 1.11.6
和python 3.5
。
我有一個用於用戶注冊的 api。
這是我的curl
命令:
curl -i -H 'Accept: application/json; indent=4' -X POST https://mydomain/users/:register/ -d "id=222111&firstname=andy&yearofbirth=2007&lastname=Chris&othernames="
當我在cygwin
使用它時,我得到了所需的響應:
HTTP/1.1 200 OK
Date: Thu, 26 Oct 2017 06:41:00 GMT
Server: Apache/2.4.18 (Ubuntu)
Allow: POST, OPTIONS
Vary: Accept,Cookie
Content-Length: 188
X-CSRFToken: acY2oPGkkqkzBe9itBq56oFeTFAllqv2bS39c7TpPN9LlGh90E1FxsI0YXLlu1Vu
X-Frame-Options: SAMEORIGIN
Set-Cookie: csrftoken=QfxnUGTmrRi1MThcn8Qau5ytnt2NR8tdRVCuIY6rWe7dwlp3UbrKV9BfsLdN0JTF; expires=Thu, 25-Oct-2018 06:41:01 GMT; Max-Age=31449600; Path=/
Content-Type: application/json
{
"isnew": "true",
"user": {
"othernames": "",
"id": "222111",
"firstname": "Andy",
"yearofbirth": 2007,
"lastnames": "Chris"
}
}
如我所見,我有X-CSRFToken
標頭和 `csrftoken' cookie。
當我嘗試從postman
運行相同的curl
命令時,我得到:
Forbidden (403)
CSRF verification failed. Request aborted.
You are seeing this message because this HTTPS site requires a 'Referer header' to be sent by your Web browser, but none was sent. This header 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 'Referer' headers, please re-enable them, at least for this site, or for HTTPS connections, or for 'same-origin' requests.
我在views.py
中的功能是:
class ApiUserRegister(APIView):
permission_classes = ()
serializer_class = RegisterUserSerializer
def post(self, request):
serializer = RegisterUserSerializer(data=request.data)
# Check format and unique constraint
serializer.is_valid(raise_exception=True)
data = serializer.data
if User.objects.filter(id=data['id']).exists():
user = User.objects.get(id=data['id'])
is_new = "false"
resp_status = status.HTTP_200_OK
else:
user = User.objects.create(id=data['id'],
firstname=data['firstname'],
yearofbirth=data['yearofbirth'],
lastname=data['lastname'],
othernames=data['othernames'])
user.save()
is_new = "true"
resp_status = status.HTTP_201_CREATED
resp = {"user": serializer.get_serialized(user),
"isnew": is_new} #csrfmiddlewaretoken: csrf_token
return Response( resp, status=resp_status, headers = {"X-CSRFToken":get_token(request)})
您可以創建一個額外的視圖來生成您可以首先通過 GET 請求收集的 CSRF 令牌。
示例:
# views.py
from django.middleware.csrf import get_token
class CSRFGeneratorView(APIView):
def get(self, request):
csrf_token = get_token(request)
return Response(csrf_token)
# urls.py
urlpatterns += [url(r'generate_csrf/$', views.CSRFGeneratorView.as_view())]
然后,您可以先調用此視圖以獲取 CSRF 令牌以用於進一步的請求。
編輯:獲取令牌后,您將其添加到表單數據中。
示例:
curl -X POST -d "csrfmiddlewaretoken=<token_value>" <url>
參考: CSRF 的工作原理
Django 在登錄時設置 csrftoken cookie。 登錄后,我們可以在 Postman 中看到來自 cookie 的 csrf 令牌。 (見圖)來自 cookie 的 CSRFtoken
第一種方法...
我們可以獲取此令牌並手動將其設置在標頭中。 但是這個令牌在到期時必須手動更改。 在到期的基礎上執行此過程變得乏味。
更好的辦法...
相反,我們可以使用 Postman 腳本功能從 cookie 中提取令牌並將其設置為環境變量。 在郵遞員的測試部分,添加這些行。
var xsrfCookie = postman.getResponseCookie("csrftoken"); postman.setEnvironmentVariable('csrftoken', xsrfCookie.value);
這將提取 csrf 令牌並將其設置為當前環境中名為 csrftoken 的環境變量。 現在在我們的請求中,我們可以使用這個變量來設置標題。(見圖)在你的標題中設置 {{csrftoken}}
當令牌過期時,我們只需要再次登錄,csrf 令牌就會自動更新。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.