Django csrf_exempt 不使用 SessionAuthentication

Django csrf_exempt not working with SessionAuthentication

我正在使用 Django Rest Framework 与用户 registration/login 一起构建一个网络应用程序。 我试图免除用户注册视图需要 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 的事实有关吗?

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

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

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