python-requests和django - CSRF验证失败。请求中止

时间:2022-04-11 06:35:26

I have a django server to upload files and when I use a browser, I can upload the file without problems.

我有一个django服务器上传文件,当我使用浏览器时,我可以毫无问题地上传文件。

But if I use the python-requests commands, it tells me CSRF verification failed. Request aborted. The python-requests code is as followed:

但是,如果我使用python-requests命令,它会告诉我CSRF验证失败。请求中止。 python请求代码如下:

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

If I execute my code, I get the code 403 and the error CSRF verification failed. Request aborted. Reason given for failure: CSRF token missing or incorrect.

如果我执行我的代码,我得到代码403并且错误CSRF验证失败。请求中止。失败原因:CSRF令牌丢失或不正确。

But if I look in the header I sent, I have the cookie set:

但是,如果我查看我发送的标题,我会设置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'})

Could you please tell me what I should do in order to have this to work?

你能否告诉我应该做些什么才能让它发挥作用?

Thanks,

John.

3 个解决方案

#1


12  

It's actually all working fine, you just have to understand how csrf works. When you load the page in your browser, you get a csrf token inside {% csrf_token %}, So when you send the data to the server, you also send along the csrf token.

它实际上一切正常,你只需要了解csrf的工作原理。当您在浏览器中加载页面时,您会在{%csrf_token%}中获得一个csrf令牌,因此当您将数据发送到服务器时,您还会发送csrf令牌。

When you use requests, you're getting the cookie in the 'get' part, but you're not sending it along with your 'post'. without it, you're just sending a post request with no token at all, which means a CSRF verification error. To solve it, try this code:

当您使用请求时,您会在“获取”部分获取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))

If this is just for your own usage, you can disable csrf on that view using csrf_exampt:

如果这仅供您自己使用,您可以使用csrf_exampt在该视图上禁用csrf:

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

But note that this isn't a recommended solution if you plan to launch your server and open it to the public

但请注意,如果您计划启动服务器并向公众开放,则不建议使用此解决方案

#2


3  

If I use the python-requests commands, it tells me CSRF verification failed. But if I look in the header I sent, I have the cookie set:

如果我使用python-requests命令,它会告诉我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

You have to send two things back to the server:

您必须将两件东西发回服务器:

1) The csrftoken cookie.

1)csrftoken cookie。

2) The following form name/value pair:

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

"csrfmiddlewaretoken" = "csrf token here"

A requests session will take care of returning the cookie for you, but you have to add the form name/value pair:

请求会话将负责为您返回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

When your django html template contains a csrf tag:

当您的django html模板包含csrf标记时:

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

{% csrf_token %}

the csrf tag is replaced by a hidden form field:

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

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

The hidden form field sends an additional name/value pair to the server along with all the other name/value pairs that the form creates. The name is "csrfmiddlewaretoken" and the value is the csrf token. django checks for the cookie as well as the name/value pair in the form data.

隐藏表单字段将另外的名称/值对以及表单创建的所有其他名称/值对发送到服务器。名称为“csrfmiddlewaretoken”,值为csrf标记。 django检查cookie以及表单数据中的名称/值对。

By the way, in order to get a csrf token for testing purposes, you can make a get request to a view that looks like this:

顺便说一句,为了获得用于测试目的的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')

#3


0  

It depends what you're trying to do.

这取决于你想要做什么。

If you do not need CSRF verification you can use the csrf_exempt decorator.

如果您不需要CSRF验证,则可以使用csrf_exempt装饰器。

Or you can create a new csrf_exempt view for only accessing through python-requests.

或者,您可以创建新的csrf_exempt视图,仅用于通过python请求进行访问。

#1


12  

It's actually all working fine, you just have to understand how csrf works. When you load the page in your browser, you get a csrf token inside {% csrf_token %}, So when you send the data to the server, you also send along the csrf token.

它实际上一切正常,你只需要了解csrf的工作原理。当您在浏览器中加载页面时,您会在{%csrf_token%}中获得一个csrf令牌,因此当您将数据发送到服务器时,您还会发送csrf令牌。

When you use requests, you're getting the cookie in the 'get' part, but you're not sending it along with your 'post'. without it, you're just sending a post request with no token at all, which means a CSRF verification error. To solve it, try this code:

当您使用请求时,您会在“获取”部分获取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))

If this is just for your own usage, you can disable csrf on that view using csrf_exampt:

如果这仅供您自己使用,您可以使用csrf_exampt在该视图上禁用csrf:

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

But note that this isn't a recommended solution if you plan to launch your server and open it to the public

但请注意,如果您计划启动服务器并向公众开放,则不建议使用此解决方案

#2


3  

If I use the python-requests commands, it tells me CSRF verification failed. But if I look in the header I sent, I have the cookie set:

如果我使用python-requests命令,它会告诉我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

You have to send two things back to the server:

您必须将两件东西发回服务器:

1) The csrftoken cookie.

1)csrftoken cookie。

2) The following form name/value pair:

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

"csrfmiddlewaretoken" = "csrf token here"

A requests session will take care of returning the cookie for you, but you have to add the form name/value pair:

请求会话将负责为您返回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

When your django html template contains a csrf tag:

当您的django html模板包含csrf标记时:

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

{% csrf_token %}

the csrf tag is replaced by a hidden form field:

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

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

The hidden form field sends an additional name/value pair to the server along with all the other name/value pairs that the form creates. The name is "csrfmiddlewaretoken" and the value is the csrf token. django checks for the cookie as well as the name/value pair in the form data.

隐藏表单字段将另外的名称/值对以及表单创建的所有其他名称/值对发送到服务器。名称为“csrfmiddlewaretoken”,值为csrf标记。 django检查cookie以及表单数据中的名称/值对。

By the way, in order to get a csrf token for testing purposes, you can make a get request to a view that looks like this:

顺便说一句,为了获得用于测试目的的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')

#3


0  

It depends what you're trying to do.

这取决于你想要做什么。

If you do not need CSRF verification you can use the csrf_exempt decorator.

如果您不需要CSRF验证,则可以使用csrf_exempt装饰器。

Or you can create a new csrf_exempt view for only accessing through python-requests.

或者,您可以创建新的csrf_exempt视图,仅用于通过python请求进行访问。