繁体   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