【问题标题】:csrfToken is only valid after page refresh - DjangocsrfToken 仅在页面刷新后有效 - Django
【发布时间】:2018-01-15 00:17:36
【问题描述】:

我在 SPA 中遇到了 Django CSRF 令牌的奇怪问题。

当我呈现我的应用程序时,我确保使用ensure_csrf_cookie 设置令牌。当我检查我的 cookie 时,我看到 csrftoken 已正确存储,并且我还使用以下命令将其作为请求的一部分发送:

     headers: {
       ‘X-CSRFToken’: getCsrfTokenFromCookie(),
     }

当我删除csrfToken cookie 并刷新页面时,会设置一个新的csrfToken,但是当我尝试发送我的请求时,我收到了错误

消息:“CSRF 失败:CSRF 令牌丢失或不正确。”

但是如果我再次刷新页面,请求会使用相同的 csrfToken cookie 成功发送!

我不确定是什么导致了这种不一致。有什么想法吗?

【问题讨论】:

标签: javascript python django reactjs token


【解决方案1】:

您的问题可能类似于this 问题。如果您强制刷新整个页面,您的问题可能会得到解决。

【讨论】:

  • 您的链接指向此处提出的问题本身。您可能需要编辑此
【解决方案2】:

我想这个问题对我的应用程序来说是非常具体的。使用 React/Redux 前端和 Django REST 框架,问题是当请求被实例化时,csrfToken 尚未设置。

【讨论】:

    【解决方案3】:

    我发现location.reload() 方法使我的 SPA(React+Redux 前端,DRF 后端)看起来很糟糕/笨拙,因为它会登录用户,然后刷新页面(尝试在不同的地方使用它,但它没有t 解决这个问题)。

    对于我的情况,both CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY are set to True

    我让登录 POST 路由在响应负载中返回“csrfToken”,然后我的身份验证减速器在处理 LOGIN_SUCCESS 操作后,会将隐藏的 csrfmiddlewaretoken 输入值更新为 csrfToken,以便它可以用于任何后续请求。

    由于只有成功通过登录路径才能获取令牌,所以从安全角度来看,这应该没问题。

    模板:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Sample</title>
    </head>
    <body>
        <div id="root"></div>
        {% load static %}
        <script>
           // global vars
           var CSRF_TOKEN = '{{ csrf_token }}';
        </script>
        <script src="{% static "frontend/main.js" %}"></script>
    </body>
    </html>
    

    查看:

    class LoginAPI(generics.GenericAPIView):
        serializer_class = LoginSerializer
    
        def post(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            user = serializer.validated_data
    
            login(request, user)
    
            return Response({
                'csrfToken': get_token(request) # from `django.middleware.csrf`; when called, refreshes the csrf token in the session and returns it
            })
    

    减速器:

    ...
    case LOGIN_SUCCESS:
    case REGISTER_SUCCESS:
        console.log(`old CSRF_TOKEN: ${CSRF_TOKEN}`);
        CSRF_TOKEN = action.payload.csrfToken;
        return {
            ...state,
            isAuthenticated: true,
            isLoading: false
        }
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-23
      • 2016-11-02
      • 1970-01-01
      • 2017-05-13
      • 2017-04-03
      • 1970-01-01
      • 2016-05-21
      相关资源
      最近更新 更多