django csrf 验证失败

转载自: python-requests和django-CSRF验证失败。请求中止 - IT宝库 (itbaoku.cn)

python-requests和django-CSRF验证失败。请求中止的处理方法

问题描述

 

我有一个用于上传文件的Django服务器,当我使用浏览器时,我可以上传文件而没有问题.

但是,如果我使用python-requrequests命令,它告诉我CSRF验证失败了.要求中止. python-requredquests代码如下:

    # upload via HTTP
    file = {"docfile": open(fullfilename, "rb")}
    s = requests.Session()
    r = s.get(dhost)
    r = s.post(dhost, files=file)

 

如果执行代码,则获得代码403,并且错误CSRF验证失败.要求中止.失败的原因:

CSRF令牌缺失或不正确.

但是,如果我在发送的标题中查看,我有cookie集:

CaseInsensitiveDict({'Content-Length': u'84169', 
'Accept-Encoding': 'gzip, deflate, compress', 
'Accept': '*/*', 
'User-Agent': 'python-requests/2.0.1 CPython/2.7.3 Linux/3.6.11+', 
'Cookie': 'csrftoken=GOOIsG89i5oMCJO6594algTXooxoUeoL', 
'Content-Type': 'multipart/form-data; boundary=86ada00b4f6c41d5997293cce7a53b6b'})

 

您能告诉我我该怎么做才能使它工作?

推荐答案

实际上一切正常,您只需要了解CSRF的工作原理即可.当您将页面加载到浏览器中时,您会在{% csrf_token %}内部获得CSRF令牌,因此,当将数据发送到服务器时,也沿CSRF令牌发送.

当您使用请求时,您将在"获取"部分中获取cookie,但是您并未将其与"帖子"一起发送.没有它,您只是发送一个没有令牌的邮政请求,这意味着CSRF验证错误.要解决它,请尝试此代码:

file = {"docfile": open(fullfilename, "rb")}
s = requests.Session()
r1 = s.get(dhost)
csrf_token = r1.cookies['csrftoken']
r2 = s.post(dhost, files=file, data={'csrfmiddlewaretoken': csrf_token}, headers=dict(Referer=dhost))

 

如果这仅是您自己的用法,则可以使用CSRF_EXAMPT在该视图上禁用CSRF:

@csrf_exempt
def my_view(request):
   ...whateva...

 

但是请注意,如果您打算启动服务器并将其打开给公共

,这不是建议的解决方案

其他推荐答案

如果我使用python-requepests命令,它告诉我CSRF验证 失败的.但是,如果我在发送的标题中查看,我有cookie集:

  'Content-Length': u'84169', 
  'Accept-Encoding': 'gzip, deflate, compress', 
  'Accept': '/', 
  'User-Agent': 'python-requests/2.0.1 CPython/2.7.3 Linux/3.6.11+',
  'Cookie': 'csrftoken=GOOIsG89i5oMCJO6594algTXooxoUeoL',
  'Content-Type': 'multipart/form-data; boundary=86ada00b4f6c41d5997293cce7a53b6b

您必须将两件事发送回服务器:

1)csrftoken cookie.

2)以下表格名称/值对:

"csrfmiddlewaretoken" = "csrf token here"

a requests会话将为您返回cookie,但您必须添加表单/值对:

sess = requests.Session()
r = sess.get(get_url)
my_csrf_token = r.cookies['csrftoken']

with open('myfile.txt') as f:
    r = sess.post(
        post_url,
        data = {
            "csrfmiddlewaretoken": my_csrf_token,
        },
        files = {"myfile": f}

)

print r.status_code
print r.text

 

当您的Django HTML模板包含CSRF标签时:

<form name="myMessage" 
      method="post" 
      class="signin" 
      action="/myapp/process_form/"
      enctype="multipart/form-data">

{% csrf_token %}

 

csrf tag被隐藏的表单字段替换:

<input type="hidden" 
       value="RTpun6OhlRehRRa2nAIcTtFJk5WuWsLg" 
       name="csrfmiddlewaretoken">

 

隐藏的表单字段将附加名称/值对以及表单创建的所有其他名称/值对发送.名称为"csrfmiddlewaretoken",值是CSRF令牌. Django检查cookie以及表单数据中的名称/值对.

顺便说一句,为了获得CSRF令牌用于测试目的,您可以将get请求发送到看起来像这样的视图:

def myview(request):
    from django.middleware.csrf import get_token
    get_token(request)  #This causes django to set the csrftoken cookie in the response

    return HttpResponse('server received GET request')

 

 
posted @ 2022-09-22 13:45  tslam  阅读(406)  评论(0编辑  收藏  举报