Django拒绝来自Python请求的请求

时间:2019-12-24 14:38:38

标签: python django python-requests

我有一个Django视图,当用户执行某些任务时,外部Python微服务会检索该数据,然后将一些数据发送到Django视图,该数据应该在模板上显示给用户。要使用Python请求发送数据,问题在于Django拒绝Json响应有两个原因:1)未设置CSRF令牌2)视图为@login_required

这是我的观点:

@login_required
def myTestView(request):    

    if request.method == 'POST':
        received_json_data=json.loads(request.body)
        print(received_json_data)
        print('received.')

这是我发送回复的方式:

import requests

req = requests.post('http://127.0.0.1:8000/myTestView/', json={"test": "json-test"})
print('SENT')

使用实际代码,我从Django收到此错误:

Forbidden (CSRF cookie not set.): /myTestView/
[2019-12-24 15:36:08,574] log: WARNING - Forbidden (CSRF cookie not set.): /myTestView/

我知道我可以使用@csrf_exempt,但是由于我发送的数据是个人数据,我希望它尽可能安全,因此我需要找到一种发送CSRF令牌的方法。我需要做的第二件事是如何使用请求“登录”?

1 个答案:

答案 0 :(得分:2)

我喜欢这个问题,所以我将尝试详细描述整个过程。

  1. 服务器端

第一步是获取csrf_token,将其用于后续的发布请求中。

之后,您必须对会话进行身份验证。

因此,让我们写一个视图来获取get以获取csrf_token并发布以进行身份​​验证会话。保护视图的想法相同。

通过身份验证后,便可以访问受保护的视图。

import json

from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, HttpResponseForbidden
from django.middleware.csrf import get_token


@login_required
def myTestView(request):
    if request.method == 'POST':
        data = request.POST.get('data')
        print(json.loads(data))
        print('received.')

    response = HttpResponse(get_token(request))
    return response


def login_view(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username=username, password=password)

        if user is not None:
            login(request, user)
            return HttpResponse('authenticated')
        else:
            return HttpResponseForbidden('wrong username or password')

    response = HttpResponse(get_token(request))
    return response

  1. 客户端

requests.post不适合此任务,因为它无法跟踪(或非常困难)请求cookie和标头。

但是您可以为此使用request.session()

Django无法处理json中的csrf_token,这就是为什么您必须在请求数据中传递json。

import json

import requests


session = requests.session()
token = session.get('http://127.0.0.1:8000/login/')

session.post('http://127.0.0.1:8000/login/',
             data={
                 'username': '<username>',
                 'password': '<password>',
                 'csrfmiddlewaretoken': token})

token = session.get('http://127.0.0.1:8000/myTestView/')
data = json.dumps({'test': 'value'})
session.post('http://127.0.0.1:8000/myTestView/',
             data={
                 'csrfmiddlewaretoken': token,
                 'data': data})

记住为视图添加urls.py

我检查了此代码,它运行良好。如果有人有改进的想法,我将乐意对其进行更新。