django 使用链接或表单注销以防止 csrf 漏洞利用

Posted

技术标签:

【中文标题】django 使用链接或表单注销以防止 csrf 漏洞利用【英文标题】:django logout using a link or form to prevent csrf exploit 【发布时间】:2012-04-13 09:02:35 【问题描述】:

在阅读 djangobook chapter 时,我遇到了提到 csrf 漏洞利用的部分,其中注销链接被放置在隐藏的恶意站点中。

在我使用 django 创建的网络应用程序中,我使用了类似的注销链接

base.html:

<a  href="% url my_logout %" > Logout </a>

my_logout 网址指向 django.contrib.auth.views.logout_then_login

urlpatterns=patterns('django.contrib.auth.views',
url(r'^logout/$', 'logout_then_login', , name = 'my_logout'),
)

现在,看了csrf攻击之后,我担心恶意网站也会给我带来麻烦。所以,我想用一个表单来注销。

我以为我可以这样做

base.html:

    ...

    <form method="post" action=".">% csrf_token %
        <input type="hidden" name="next" value="next" />
        <input type="hidden" name="confirm" value="true" />
        <input type="submit" value="Logout" />
    </form>
...

现在,我应该如何编写处理这个表单的视图?如果我要处理隐藏变量(confirm 检查是否应该注销,next 转到上一个视图),我还会能用django.contrib.auth.views.logout_then_login方法吗?

有人可以告诉我这样做是否正确吗?

提前致谢

【问题讨论】:

【参考方案1】:

你可以像这样包装它

from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.http import require_POST

@csrf_protect
@require_POST
@never_cache
def safer_logout(request):
    # 'confirm' is useless here, POST implies 'do it'
    return logout_then_login(request, request.POST.get('next'))

另外,考虑使用SESSION_COOKIE_HTTPONLY

【讨论】:

@ClaudeVedovini 只是觉得有人在我编辑它时打字很快,哈哈 =p 我打算发布几乎相同的答案 :) 无论如何,我要补充一点,我认为这不是真的有用。 CSRF 漏洞利用被用来欺骗用户在他们登录的应用程序中完成操作,强制他们退出并没有真正的意义。 @ClaudeVedovini 是的,但有时当攻击者打算让您注销一段时间或等待您的新登录过程时,它会造成伤害 谢谢大家......不过是一个小问题......无论我从哪里注销,下一个参数都会返回空字符串。它不会在表单中自动设置吗? 不传入request.POST.get('next')怎么办

以上是关于django 使用链接或表单注销以防止 csrf 漏洞利用的主要内容,如果未能解决你的问题,请参考以下文章

一个令牌与多个令牌以防止 CSRF 攻击

注销时 Django CSRF 验证失败

CSRF 令牌丢失或不正确 - 在 Django 中使用自动完成灯

Django 给出“CSRF 令牌丢失或不正确”。即使在 POST 调用中传递它之后也会出错

注册表单不起作用(CSRF 令牌丢失或不正确。) django

Django - 在同一个模板(ajax 和表单)中处理多个 CSRF 令牌禁止(CSRF 令牌丢失或不正确。)