我能够使用GET来使用SessionAuthentication和Tastypie而不设置除content-type
到application/json
之外的任何标题。然而,即使标头中的Cookie具有会话ID,HTTP POST也会失败。它失败了401 AuthorizationHeader,但它与授权无关。将SessionAuthentication更改为BasicAuthentication并传递用户名/密码也可以。
有没有人用SessionAuthentication与Tastypie一起使用POST?
答案 0 :(得分:10)
是的,我已经开始工作了。您需要做的就是传递csfr令牌:
SessionAuthentication
此身份验证方案使用内置功能 用于检查用户是否已记录的Django会话。这通常很有用 当Javascript在托管API的同一网站上使用时。
它要求用户已登录&有一个活跃的会话。 他们 也必须有一个有效的CSRF令牌。
这是你在jQuery中的表现方式:
// sending a csrftoken with every ajax request
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
crossDomain: false, // obviates need for sameOrigin test
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
}
}
});
$.ajax({
type: "POST",
// ...
请注意$.cookie('csrftoken')
部分。它从Django设置的cookie中获取csrf令牌。
我在Django没有在Firefox和Opera上设置cookie时遇到了一些问题。将模板标记{% csrf_token %}
放入模板可解决此问题。正确的解决方案可能是使用装饰器ensure_csrf_cookie()
。
答案 1 :(得分:3)
以下是丹的答案的一些补充。如果出现问题,请纠正我,我自己仍然有点困惑。
在继续之前,请阅读CSRF protection in Django。 仔细阅读。您需要将Cookie中的令牌放入标题X-CSRFToken
。如果Cookie是Httponly,也就是说,如果您在CSRF-COOKIE-HTTPONLY = True
中设置了settings.py
,则无效。然后,您必须将cookie嵌入到文档中,当然,这会创建更多漏洞并减少使用Httponly
所获得的保护。
据我所知,如果cookie不是Httponly
, jQuery会自动设置X-CSRFToken 。如果我错了,请纠正我,但我只花了几个小时玩它,这就是我一直得到的。这让我想知道,Django文档中的建议有什么意义?它是jQuery中的新功能吗?
进一步讨论:
Tastypie禁用CSRF保护,但会话身份验证除外,它在authentication.py
中具有自定义代码。您必须同时传递cookie csrftoken
cookie和标头X-CSRFToken
才能使身份验证生效。 (这是Tastypie的要求。)假设同一个域,浏览器将传递cookie。除非csrftoken cookie是Httponly,否则JQuery会为你传递标题。相反,如果cookie是Httponly,我甚至无法在$.ajaxSetup{beforeSend...
中手动设置标题。如果null
cookie是Httponly,jQuery似乎会自动将X-CSRFToken设置为csrftoken
。至少我能够将标题X-CS_RFToken设置为我想要的,所以我知道我正确地传递了值。我正在使用jQuery 1.10。
如果您使用curl
进行测试,则必须传递两个Cookie(sessionid
和csrftoken
),设置标头X-CSRFToken
,如果协议是HTTPS ,还设置Referrer
。
答案 2 :(得分:-1)
我在tastypie源代码中找到了这个。基本上暗示SessionAuthentication不支持HTTP POST。
class SessionAuthentication(Authentication):
"""
An authentication mechanism that piggy-backs on Django sessions.
This is useful when the API is talking to Javascript on the same site.
Relies on the user being logged in through the standard Django login
setup.
Requires a valid CSRF token.
"""
def is_authenticated(self, request, **kwargs):
"""
Checks to make sure the user is logged in & has a Django session.
"""
# Cargo-culted from Django 1.3/1.4's ``django/middleware/csrf.py``.
# We can't just use what's there, since the return values will be
# wrong.
# We also can't risk accessing ``request.POST``, which will break with
# the serialized bodies.
if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
return request.user.is_authenticated()
所以在这里回答我自己的问题,但如果有人能够更好地解释并建议一个好的方法来做到这一点,那也会很棒。
修改
我目前正在使用来自https://github.com/amezcua/TastyPie-DjangoCookie-Auth/blob/master/DjangoCookieAuth.py的解决方法,它基本上是一种自定义身份验证方案,从Cookie中提取session_id
并检查后端是否经过身份验证。可能不是最全面的解决方案,但效果很好。