Django:使用@login_required和设置LOGIN_URL时的信息泄露问题

Posted

技术标签:

【中文标题】Django:使用@login_required和设置LOGIN_URL时的信息泄露问题【英文标题】:Django: information leakage problem when using @login_required and setting LOGIN_URL 【发布时间】:2011-01-03 18:33:53 【问题描述】:

我在使用@login_required 装饰器并设置LOGIN_URL 变量时发现了一种信息泄露形式。

我有一个网站,所有内容都需要强制登录。问题是当它是现有页面时,您会被重定向到设置了下一个变量的登录页面。

所以当没有登录并请求时:

 http://localhost:8000/validurl/

你看到了:

 http://localhost:8000/login/?next=/validurl/

当请求一个不存在的页面时:

 http://localhost:8000/faultyurl/

你看到了:

 http://localhost:8000/login/

这揭示了一些我不想要的信息。我想过重写登录方法,强制下一个为空并在这个子类方法上调用“超级”。

另一个问题是我的一些测试在没有设置 LOGIN_URL 的情况下失败。他们重定向到“/accounts/login/”而不是“/login/”。因此,为什么我想使用 LOGIN_URL 但禁用“自动下一个”功能。

任何人都可以对这个主题有所了解吗?

非常感谢。

杰拉德。

【问题讨论】:

IMO,这是半正确的行为。对于不存在的资源,您确实应该返回 404,对于需要授权才能查看的现有资源,您应该返回 403。换句话说,您不应该将不存在的内容定向到登录页面 - 显示一个非常简单的 404 页面。 【参考方案1】:

您可以将此行作为urls.py 文件中的最后一个模式。它会将不匹配任何其他模式的 url 重新路由到登录页面。

urlpatterns = patterns('',

    ...

    (r'^(?P<path>.+)$', 'django.views.generic.simple.redirect_to', 
        'url': '/login/?next=/%(path)s', 
        'permanent': False
    ),
)

编辑:要继续向经过身份验证的用户提出 404 页面,请执行以下操作:

from django.http import Http404, HttpResponseRedirect
def fake_redirect(request, path):
    if request.user.is_authenticated:
        raise Http404()
    else:
        return HttpResponseRedirect('/login/?next=/%s' % path)

urlpatterns = patterns('',

    ...

    (r'^(?P<path>.+)$', fake_redirect),
)

【讨论】:

jbochi,有趣的解决方案。但是,这会破坏正确登录的人的正常 404 行为。我必须检查我的自定义 404 处理程序的影响程度。它检查是否有人登录,然后决定 404 或登录。我看到那里出现了一个循环:) @GerardJP。你说得对!我已经编辑了我的答案。请参阅第二种解决方案。如果需要,您可以修改 raise Http404() 行以调用您的自定义 404 处理程序。 jbochi,太棒了!那确实是我要找的那个。目前我选择稍微放松一下测试,并禁用 LOGIN_URL,因为它是由我的 404 处理程序处理的。否则,我只会为我不使用的变量实现一些代码,除了它会破坏我的测试。但我肯定会记得“抓住一切”的网址技巧。再次感谢! 很高兴能帮上忙!请记住,如果您喜欢,可以将答案设置为已接受。

以上是关于Django:使用@login_required和设置LOGIN_URL时的信息泄露问题的主要内容,如果未能解决你的问题,请参考以下文章

Django:使用@login_required和设置LOGIN_URL时的信息泄露问题

使用 @login_required 时的 Django 缓存

为啥Django在使用@login_required装饰器时有太多的登录重定向?

django的权限认证:登录和退出。auth模块和@login_required装饰器

Django @login_required 删除 https

使用Django自带的登录访问限制login_required