Django - 登录 - 禁止(CSRF 令牌丢失或不正确。):

Django - Login - Forbidden (CSRF token missing or incorrect.):

我在尝试使用登录页面时收到 Forbidden (CSRF token missing or incorrect.) 错误。

场景如下:

  1. 一个用户打开了两个标签页。
  2. 两个选项卡都是登录页面。
  3. 在选项卡 1 中,用户成功登录,并被重定向到需要登录的新页面。
  4. 在tab 2,用户没有刷新页面,还在登录页面。在Django后台,用户已经认证过了,但是前端模板还没有注意到。
  5. 在选项卡 2 中,当我点击登录按钮时,出现 Forbidden (CSRF token missing or incorrect.) 错误。
  6. 我确保 csrf_token 在表格中。
  7. 仅当我使用两个选项卡时才会出现此错误。
  8. 我正在使用 AJAX

为什么会这样?我该如何解决?

我不知道这会有帮助,但这是我的views.py 登录

class Login_View(LoginView):

    template_name = 'login.html'

    def post(self, request, *args, **kwargs):
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)

        response_data = {}
        if user is not None:
            if user.is_active:
                login(request, user)
                response_data['result'] = 'success'
            else:
                return HttpResponse("Inactive user.")
        else:
            response_data['result'] = 'fail'

        return HttpResponse(json.dumps(response_data), content_type="application/json")

文档中解决了原因 here:

For security reasons, CSRF tokens are rotated each time a user logs in. Any page with a form generated before a login will have an old, invalid CSRF token and need to be reloaded. This might happen if a user uses the back button after a login or if they log in a different browser tab.

至于修复它,既没有直接的方法也没有很好的理由这样做。如果用户在这种不太可能发生的情况下遇到错误,他们所要做的就是重新加载页面。所以如果我是你,我不会打扰。

如果出现这样的情况,用户打开 2 个选项卡并尝试登录,这不是现实生活中的情况,但如果你愿意,你可以这样做,记住用户喜欢这样玩

def post(self, request, *args, **kwargs):
        username = request.POST['username']
        password = request.POST['password']
        if request.user.is_authenticated():
            return redirect('to_some_page')
        else:
            user = authenticate(username=username, password=password)

            response_data = {}
            if user is not None:
                if user.is_active:
                    login(request, user)
                    response_data['result'] = 'success'
                else:
                    return HttpResponse("Inactive user.")
            else:
                response_data['result'] = 'fail'