python - 没有在 Django 中使用 Python 请求设置 CSRF 令牌
问题描述
我正在尝试使用 Python-Request 从普通 Python 脚本向 Django 视图发送 POST 请求。django 视图不是 @login_required
,所以除了我的 JSON 数据之外,我唯一需要发送的是 CSRF 令牌,这是我尝试过的:
token = session.get('http://127.0.0.1:8000/myview/view')
data = json.dumps({'test': 'value'})
session.post('http://127.0.0.1:8000/myview/myview',
data={
'csrfmiddlewaretoken': token,
'data': data})
django 视图应该只接收请求并将其打印到我的控制台:
def myview(request):
if request.method == 'POST':
data = request.POST.get('data')
print(json.loads(data))
print('received.')
response = HttpResponse(get_token(request))
return response
我当前代码的问题是我的控制台会抛出一个log: WARNING - Forbidden (CSRF token missing or incorrect.)
. 我不能使用@csrf_exempt
,因为我需要它尽可能安全。有什么建议吗?提前致谢!
解决方案
为什么用户登录后会遇到 CSRF 验证失败?
出于安全原因,每次用户登录时都会轮换 CSRF 令牌。任何页面
登录前生成的表单将具有旧的、无效的 CSRF 令牌,需要重新加载。如果用户在登录后使用后退按钮或登录不同的浏览器选项卡,则可能会发生这种情况。
这也适用于 cookie。登录后,django 会向客户端发送一个新的 csrf cookie。这将存储在 client.cookies 中并替换旧的。django 服务器不保留旧令牌的任何记录,这就是为什么您会得到“CSRF 令牌丢失或不正确”的原因。回复。
您可以像以前一样从 request.cookies['csrftoken'] 访问新令牌。
import requests
LOGIN_URL = 'http://127.0.0.1:8000/myview/view'
request = requests.session()
request.get(LOGIN_URL)
# Retrieve the CSRF token first
csrftoken = request.cookies['csrftoken']
r1 = request.post(LOGIN_URL, headers={'X-CSRFToken': csrftoken},
allow_redirects=False))
new_csrftoken = r1.cookies['csrftoken']
data = json.dumps({'test': 'value'})
payload = {'csrfmiddlewaretoken': new_csrftoken,'data':data }
实际上,您可以直接使用客户端 cookie。这本来可以避免这个错误。当您使用 requests.session() 时,Requests 会为您跟踪 cookie。
try :
r2 = request.post('http://127.0.0.1:8000/myview/myview', data=payload, headers={'X-CSRFToken': r1.cookies['crsftoken']})
except :
print('error expected')
推荐阅读
- python - 带有数据权重的 scipy.stats.mannwhitneyu 版本
- flutter - 如何在flutter上制作图标和文字翻译动画
- go - fyne GUI compile to Web Assembly failed
- javascript - 重新加载浏览器后,window.beforeunload 事件仍然在尝试存在页面时显示确认警报
- vue.js - Vuetify 数据表项。
未应用模板 - 但其他模板很好 - reactjs - 根据当前路径在 React Router 中设置活动链接
- r - 使用 R 中的数据集位置进行过滤
- python - 如何使用调试符号轻松安装 pywin32
- ios - 无效的苹果应用程序站点关联文件格式
- powershell - Powershell重命名文件,名称中间有序号