【问题标题】:Django csrf_exempt not working with SessionAuthenticationDjango csrf_exempt 不使用 SessionAuthentication
【发布时间】:2017-01-14 23:31:11
【问题描述】:

我正在使用 Django Rest Framework 来构建一个带有用户注册/登录的 web 应用程序。 我试图免除用户注册视图需要 CSRF 令牌。这是我现在的视图:

class UserSignUpView(generics.CreateAPIView):
    permission_classes = [] # FIXME: doesn't seem to be working
    serializer_class = UserSerializer

    @method_decorator(csrf_exempt)
    def post(self, request, *args, **kwargs):
        super().post(self, request, *args, **kwargs)

    def get_permissions(self):
        if self.request.method == 'POST':
            return (permissions.AllowAny(), TokenHasReadWriteScope())
        return False

我的 settings.py 如下所示:

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': [
       'rest_framework.permissions.AllowAny',
    ]
}

我仍然在我的后端输出 Forbidden (CSRF cookie not set.): /users/ 和前端经典的 CSRF verification failed. Request aborted. 上得到这个

为什么这不起作用?这可能与我从未手动设置 CSRF cookie 的事实有关吗?

【问题讨论】:

  • get_permissions 不需要装饰器 csrf_exempt?您正在使用 POST 方法。你可以写@csrf_exempt:Documentation
  • 你也可以看this post
  • @Wilfried 我尝试将@method_decorator(csrf_exempt) 添加到get_permissions 的顶部,但没有变化

标签: python django django-rest-framework django-csrf


【解决方案1】:

Django REST 框架已经通过在任何APIView 上使用csrf_exempt 来阻止CSRFViewMiddleware 执行CSRF 检查。相反,当用户使用SessionAuthentication 成功验证身份时,它会显式调用 CSRF 检查。你不能绕过这个检查,你也不应该。常规的 Django 视图可能不依赖于会话,在这种情况下,CSRF 攻击是不可能的,您可以使用csrf_exempt 来表明这一点。当您使用SessionAuthentication 时,您容易受到 CSRF 攻击,您需要检查以防止攻击。在这种情况下绕过检查总是会给您带来漏洞,这就是 DRF 不允许您禁用检查的原因。

你基本上有两种选择来解决这个问题:

  • 确保用户未成功通过SessionAuthentication 的身份验证。
  • 确保已设置 cookie,并在 X-CsrfToken 请求标头中发送令牌。

【讨论】:

  • 我不明白 SessionAuthentication 与 CSRF 保护有何关系。我看到在 Django 中,没有后者就不能拥有前者,但我不明白为什么会这样。
  • CSRF 攻击是一种在您不知情的情况下滥用会话的方式。如果您没有会话或类似机制,则攻击者无法通过伪造跨站点请求来滥用任何内容。
  • 感谢您的解释。完全有道理。所以只是解释一下,如果使用SessionAuthentication 进行身份验证,csrf_exempt 没有任何效果。那么csrf_exempt 在什么情况下真的有用呢?根据我的阅读,只有在使用SessionAuthentification时才会检查CSRF,所以使用csrf_exempt否则是没用的,因为无论如何都不检查CSRF。
  • 在 Django REST 框架内?绝不。但是,Django 没有实现相同的SessionAuthentication,因此它不知道哪些视图易受攻击,由您决定哪些视图应该受到保护。在这种情况下,您可以在不易受攻击的视图上使用 csrf_exempt
猜你喜欢
  • 2014-01-08
  • 2013-10-12
  • 2015-09-03
  • 2016-02-28
  • 1970-01-01
  • 2019-01-16
  • 2022-01-13
  • 2019-07-13
  • 2017-06-02
相关资源
最近更新 更多