【问题标题】:Getting a 403 error involving CSRF when trying to connect to localhost (python requests)尝试连接到本地主机时出现涉及 CSRF 的 403 错误(python 请求)
【发布时间】:2018-07-30 07:10:14
【问题描述】:

我正在尝试使用 Python 的 requests 库测试与我的 Django 视图之一的连接。当我尝试对其发出POST 请求时,我在查看request.text 时收到信息,告诉我CSRF 验证失败,并且在提交表单时我需要一个CSRF 令牌。我在这里做了更多的研究,并尽我所能

这是我现在的代码:

post_request = requests.session()
post_request.get('http://127.0.0.1:8000/message/')
csrftoken = post_request.cookies['csrftoken']

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36'}
final_request = post_request.post('http://127.0.0.1:8000/message/', headers=dict(Referer=post_request))

这是我的看法:

def add_message(request):
    form = InputInfoForm(request.POST)

    if request.method == 'POST':
        return HttpResponse('hey')

    return HttpResponse('test')

那么如何使用请求验证视图中的 CSRF 令牌?

【问题讨论】:

    标签: python django python-requests


    【解决方案1】:

    您的代码存在以下问题。 Django 希望您的 cookie 中包含 CSRFTOKEN,但您的帖子参数也必须提供带有 csrfmiddlewaretoken 名称的帖子数据。所以,使用python请求方法,

    post_request = requests.session()
    post_request.get('http://127.0.0.1:8000/message/')
    csrftoken = post_request.cookies['csrftoken']
    #now the csrftoken cookie is stored in csrftoken
    final_request = post_request.post('http://127.0.0.1:8000/message/', data = {'csrfmiddlewaretoken' : csrftoken}, cookies=post_request.cookies) #assuming the post data for your form is empty, else add in the 'data' dictionary. just check your 'InputInfoForm' form for any fields. 
    final_request.text  #will read you the data returned from the view, in your case "hey"
    

    在您看来,进行以下更改,

    from django.shortcuts import render  #needed
    def add_message(request):
        form = InputInfoForm(request.POST)
    
        if request.method == 'POST':
            return HttpResponse('hey')
    
        return render(request, 'test.html')  #assuming no context...
    

    在您的应用文件夹中,添加一个“模板”文件夹并在模板中创建“test.html”文件。然后添加以下内容

    <form method="POST" action="{% url 'message:test'%}">{%csrf_token%}</form>
    

    然后在项目文件夹的 urls.py 中,添加

    from django.conf.urls import url, include
    urlpatterns = [
    #admin_page --snip--
    url(r'^message/', include('APPNAME.urls', namespace='message')),
    ]
    

    然后在您的应用文件夹中,创建一个“urls.py”文件并添加以下内容...

    from .views import add_message #your view
    from django.conf.urls import url
    
    app_name = "APP_NAME"  #from django2.0 on wards 
    urlpatterns = [
        url(r'^$', add_message, name='test'), 
    ] 
    

    那么你就可以走了。通过运行上面的 python 代码来检查。

    【讨论】:

    • 它仍然不适合我,我似乎能够隔离问题。例如,当我运行 r = requests.get('http://127.0.0.1:8000/message/') 时,它显示一个空集:&lt;RequestsCookieJar[]&gt; 所以看起来我没有收到 cookie
    • 在您的模板中,您是否在帖子表单标签中包含了 {%csrf_token%}?或任何中间件的删除或移除将使您的页面呈现没有任何 csrftoken cookie。也检查一下。
    • 不,我在没有模板的情况下这样做
    • 那你怎么能在没有模板的情况下渲染任何 cookie 或页面呢??
    • 我没有渲染页面,我只是使用模型添加到 Db。并使用请求来这样做。至于 cookie,我不确定是否需要一个模板
    【解决方案2】:

    您应该在 POST 数据中发送 CSRF 令牌

    r = post_request.post(
        'http://127.0.0.1:8000/message/', 
        data={'csrfmiddlewaretoken': csrftoken},
        headers=dict(Referer=URL)
    )
    

    发送 CSRF 令牌的另一种方法是通过标头

    r = post_request.post(
        'http://127.0.0.1:8000/message/', 
        headers={'Referer': URL, 'X-CSRFToken': csrftoken)
    )
    

    HTTP_X_CSRFTOKEN 是默认值settings.CSRF_HEADER_NAME

    【讨论】:

    • 好的,我需要用 cookie 中的实际 csrftoken 替换 csrftoken 吗?
    • nvm 这个问题,但我似乎仍然收到错误
    • 我在csrfmiddlewaretoken=csrftoken 收到一个无效的语法错误,这不应该是一本字典吗?
    • @Amon 是的,它应该是 dict
    • 问题依旧,不知道是什么问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 2023-02-10
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 2013-07-08
    • 1970-01-01
    相关资源
    最近更新 更多