Django: 如何在服务器端使用CSRF令牌进行POST请求

3

我的网站使用Django的默认认证模块进行用户认证。通常,用户只需要在登录页面上填写用户名和密码并点击提交按钮,然后经过CSRF保护的数据将被发布到Django认证终端/auth/login/

但出于某种原因,我现在还需要在我的服务器上进行此操作。这与后端身份验证服务器相同。经过研究和试错,我最终得到了:

from django.views.generic import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect
import requests

class fb_login(View):
    "login view for Facebook OAuth"

    @method_decorator(csrf_protect)
    def get(self, request):
        ''' code that gets username and password info. from user's FB profile
        is not shown here '''

        # login code
        url = 'http://localhost:8000/auth/login/'
        client = requests.session()
        # Retrieve the CSRF token first
        client.get(url)  # sets cookie
        csrftoken = client.cookies['csrftoken']
        form = {'username': uname, 'password': pw}
        header = {'X-CSRFToken': csrftoken}
        resp = requests.post(url, data=form, headers=header)

我也尝试将csrf令牌添加为表单字段的一部分:
form = {'username': uname, 'password': pw , 'csrfmiddlewaretoken': csrftoken}
resp = requests.post(url, data=form)

我基本上只是按照Django文档操作。但我仍然遇到了403错误,提示CSRF verification failed, CSRF cookie not set。我想知道我是否漏掉了什么步骤?我已经仔细检查了Django文档中的过程,但我找不到任何可能出错或遗漏的地方。


你的页面模板中的表单标签内是否包含{% csrf_token %} - John Gordon
@JohnGordon 是的。在客户端登录没有问题,这通常是通过 {% csrf_token %} 进行表单提交操作。但现在我需要在服务器端实现这个功能。 - J Freebird
我刚刚查看了一个表单发送的数据,它发送了表单数据 csrfmiddlewaretoken=xxx 和 cookie csrftoken=xxx。也许你需要设置 cookie 而不是/以及表单字段。 - rodrigo
@JFreebird:嗯,我在我的视图中使用CSRFMiddleware和render()函数,并且它会自动处理。请参阅文档以了解其他选择。 - rodrigo
@rodrigo 我会看一下,谢谢。你的服务器端请求能够通过 CSRF 保护吗? - J Freebird
显示剩余3条评论
1个回答

1

正如@rodrigo所建议的那样,为了通过CSRF安全检查,还需要使用cookies。下面是一个简单的代码片段:

csrftoken = requests.get(url).cookies['csrftoken']
form = {'username': uname, 'password': pw}
header = {'X-CSRFToken': csrftoken}
cookies = {'csrftoken': csrftoken}
resp = requests.post(url, data=form, headers=header, cookies=cookies)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接