我有一个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令牌的方法。我需要做的第二件事是如何使用请求“登录”?
答案 0 :(得分:2)
我喜欢这个问题,所以我将尝试详细描述整个过程。
第一步是获取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
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
我检查了此代码,它运行良好。如果有人有改进的想法,我将乐意对其进行更新。