6

我可以使用 GET 来使用 SessionAuthentication 和 Tastypie,而无需设置除content-typeto之外的任何标头application/json。然而,即使 Header 中的 Cookie 具有会话 ID,HTTP POST 也会失败。它以 401 AuthorizationHeader 失败,但与授权无关。将 SessionAuthentication 更改为 BasicAuthentication 并传递用户名/密码也可以。

有没有人让 SessionAuthentication 与 Tastypie 一起使用 POST?

4

3 回答 3

10

是的,我已经让它工作了。您需要做的就是传递 csfr 令牌:

会话认证

此身份验证方案使用内置的 Django 会话来检查用户是否已登录。这在托管 API 的同一站点上由 Javascript 使用时通常很有用。

它要求用户已登录并具有活动会话。他们还必须有一个有效的 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 %}模板中可以解决这个问题。正确的解决方案可能是使用 decorator ensure_csrf_cookie()

于 2013-03-13T17:53:39.837 回答
3

以下是丹的回答的一些补充。如果有问题,请纠正我,我自己还是有点困惑。

在继续之前,请阅读Django 中的 CSRF 保护仔细阅读。您需要将 cookie 中的令牌放入 headerX-CSRFToken中。如果 cookie 是 Httponly,这将不起作用,也就是说,如果您设置CSRF-COOKIE-HTTPONLY = Truesettings.py. 然后您必须将 cookie 嵌入到文档中,这当然会产生更多漏洞并减少使用Httponly.

据我所知,如果 cookie 不是HttponlyjQuery 会自动设置 X-CSRFToken。如果我错了,请纠正我,但我刚刚花了几个小时玩它,这就是我一直得到的。这让我想知道,Django 文档中的建议有什么意义?它是 jQuery 中的新功能吗?

进一步讨论:

Tastypie 禁用 CSRF 保护,但会话身份验证除外,它在authentication.py. 您必须同时传递 cookie csrftokencookie 和标头X-CSRFToken才能进行身份验证。(这是 Tastypie 的要求。)假设域相同,浏览器将传递 cookie。除非 csrftoken cookie 是 Httponly,否则 JQuery 将为您传递标头。相反,如果 cookie 是 Httponly,我什至无法在$.ajaxSetup{beforeSend.... null如果csrftokencookie 是 Httponly ,jQuery 会自动将 X-CSRFToken 设置为。至少我能够将标头 X-CS_RFToken 设置为我想要的,所以我知道我正确地传递了这个值。我正在使用 jQuery 1.10。

If you are using curl for testing, you have to pass two cookies (sessionid and csrftoken), set the headers X-CSRFToken and, if the protocol is HTTPS, also set the Referrer.

于 2014-04-23T00:01:42.610 回答
-1

我在tastepie 源代码中找到了这个。基本上意味着 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的解决方法,它基本上是一个自定义身份验证方案,它session_id从 cookie 中获取并检查后端是否存在已通过身份验证。可能不是最完整的证明解决方案,但效果很好。

于 2013-03-13T16:25:32.743 回答