csrfToken仅在页面刷新后有效 - Django

时间:2017-08-07 16:02:01

标签: javascript python django reactjs token

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

当我渲染应用程序时,我确保使用ensure_csrf_cookie设置令牌。当我检查我的cookie时,我看到csrftoken已正确存储,我也将其作为请求的一部分发送:

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

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

  

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

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

我不确定导致这种不一致的原因。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

我认为这个问题对我的申请非常具体。使用React / Redux前端和Django REST框架,问题发现当实例化请求时,尚未设置csrfToken。

答案 2 :(得分:0)

我发现location.reload()方法使我的SPA(React + Redux前端,DRF后端)看起来不好/笨拙,因为它将使用户登录,然后刷新页面(尝试在其他位置使用它,没有解决这个问题。)

根据我的情况,both CSRF_USE_SESSIONS and CSRF_COOKIE_HTTPONLY are set to True

我使登录POST路由在Response有效负载中返回“ 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
    }
...