在梳理如何根据django应用正确认证python-request
客户端以允许POST
时遇到麻烦。我们的代码尝试首先登录,然后使用已建立的python-request
会话来处理POST
数据,但是我们的POST
请求始终未经身份验证。
这就是我们正在尝试的
# client.py
LOGIN_URL = 'http://localhost/accounts/login'
ADD_URL = 'http://localhost/add'
import requests
rqst = requests.session()
rsp = rqst.get(LOGIN_URL)
token = rsp.cookies['csrftoken']
rsp = rqst.post(LOGIN_URL, auth=(uname, pwd),
data={'csrfmiddlewaretoken':token, 'next':'/'})
# at this point, rsp.status_code == 200 and we are logged in
payload = {'foo':'bar', 'csrfmiddlewaretoken':token}
rsp = rqst.post(ADD_URL, json=payload)
# Error -- this post always returns 403 -> HttpResponseForbidden
# view.py
def view_add(request):
if request.user.is_authenticated:
return HttpResponseForbidden('not authenticated')
...
我们已在settings.py
中启用了django会话。使用相同的模式访问GET
视图是没有问题的。这是我们遇到麻烦的唯一POST
。
有什么主意吗?
答案 0 :(得分:1)
我想补充一下user590028的示例对我有帮助,但是出于某种原因,如果是这样设置服务器,则在LOGIN_URL之后添加/是很重要的。
在我项目的urls.py中:
urlpatterns = [
path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
]
因此,此操作不起作用:http://localhost:8000/login <-不加斜杠!
这有效:http://localhost:8000/login/
...我花了很长时间才弄清楚这一点,因此希望对其他人有帮助。
也-有一篇非常不错的Python抓取文章,它也帮助我找到了csrf令牌: https://kazuar.github.io/scraping-tutorial/
答案 1 :(得分:0)
您的第二个POST请求没有CSRF令牌(即使登录请求也没有)。
除非您的视图被标记为@csrf_exempt
,否则所有非GET请求都需要CSRF令牌。
答案 2 :(得分:0)
该问题是由我对Django身份验证的困惑引起的。 Django身份验证基于表单,而rqst.post(..., auth=(uname, pwd))
默认为basic authentication。
因此,错误是在rqst.post()
的第一次调用中发生的。正确的代码client.py是:
# client.py
LOGIN_URL = 'http://localhost/accounts/login'
ADD_URL = 'http://localhost/add'
import requests
rqst = requests.session()
rsp = rqst.get(LOGIN_URL)
token = rsp.cookies['csrftoken']
rsp = rqst.post(LOGIN_URL,
data={'username':uname, 'password': pwd, # <---- HERE IS FIX
'csrfmiddlewaretoken':token, 'next':'/'})
答案 3 :(得分:-1)
在django项目之前,我在request.sessions上遇到过问题。我确信它是可行的,但是我发现将Selenium用作无头浏览器更加容易。 python对硒有很好的支持,并且入门非常简单。