簡體   English   中英

Django rest-api:郵遞員看不到 CSRF 令牌

[英]Django rest-api: Postman can't see CSRF token

我在ubuntu服務器上使用django 1.11.6python 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 令牌就會自動更新。

感謝來自hackernoon.com 的@chillaranand的原始帖子

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM