Django Allauth CSRF验证失败错误

3
让我解释一下我正在做什么?
我在浏览器上打开了两个选项卡,都显示我的登录页面(简单的用户名和密码表格)。
使用选项卡1:我使用正确的凭据登录。运行正常。
使用选项卡2:(不刷新)我再次尝试使用相同或不同的凭据登录,这会引发403禁止错误。失败原因是:CSRF令牌缺失或不正确。
我知道,我正在做一些傻事,那就是当我已经登录时尝试登录。
我想防止出现错误403,并使流程顺畅,即第二次登录请求应该被忽略,当某人已经登录或其他不会中断流程的情况下。我该如何处理?
我正在使用Django==1.6.2和django-allauth==0.14.1。
2个回答

8
首先,让我们简单了解一下背景,或许你会觉得很有趣:这部分与CSRF令牌和会话相关。

在Django中,CSRF的工作方式是在模板和会话中镜像相同的令牌——这就是Django检查传入表单数据是否匹配用户会话并且不是来自恶意注入的方式。

当您从未登录到已登录时,您正在将未经身份验证的会话交换为经过身份验证的会话,这意味着您会获得一个新的会话,其中包含会话中的新CSRF令牌。该会话在所有标签之间共享,即使是在Chrome等每个标签具有单独进程的浏览器中也是如此。

因此,在选项卡A上登录会向选项卡B提供一个会话cookie,该cookie不再与页面中嵌入的CSRF令牌匹配,因此选项卡B会抛出CSRF异常。如果在选项卡A上登录后刷新选项卡B(并假设已登录的用户仍然可以看到登录屏幕),则应允许您再次登录,因为刷新后的页面的CSRF令牌将再次与会话中的令牌匹配。

至于优雅地处理此问题,我建议您添加一个自定义403处理程序视图,它可以显示您自己设计的更漂亮的403页面,或者——如果您认为这是可以接受的——将用户重定向到其他地方(但我会检查此重定向是否仅在响应于您问题中描述的虚假登录时发生)。

另外要说的一件事是:您所谈论的用例(两个标签打开)非常少见-我只会使用自定义403页面使其更漂亮,而不是重定向。


如果您有兴趣,请查看源代码

if SESSION_KEY in request.session:
    if request.session[SESSION_KEY] != user.pk:
        # To avoid reusing another user's session, create a new, empty
        # session if the existing session corresponds to a different
        # authenticated user.
        request.session.flush()
else:
    request.session.cycle_key()

当你从未经过身份验证的用户开始时,这个用户的.pk与您已经进行身份验证的用户的PK不可能相同,因此您将获得一个新的会话。

(如果您再次以相同用户身份登录,则会调用cycle_key()函数,这可能会保留CSRF令牌 - 我没有检查过)


-3
你应该像这样做:
def userlogin(request):
    if request.method=='POST':
        user = request.user
        if user.is_authentificated:
            return HttpResponceRedirect('some_url')
        else:
            #your login procedure

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接