简体   繁体   English

Flask 当 JWT_COOKIE_CSRF_PROTECT=True 时 POST 请求失败

[英]Flask POST requests fail when JWT_COOKIE_CSRF_PROTECT=True

My POST requests to flask backend only work with JWT_COOKIE_CSRF_PROTECT = False, but GET requests work我对 flask 后端的 POST 请求仅适用于 JWT_COOKIE_CSRF_PROTECT = False,但 GET 请求有效

config:配置:

CSRF_ENABLED = True   
CORS_SUPPORTS_CREDENTIALS = True   
JWT_TOKEN_LOCATION = ['cookies']

I access flask through axios from the Vue app我从 Vue 应用程序访问 flask 到 axios

  const path1 = `/limit_engine/balance`;
  axios
    .post(path1, { withCredentials: true })
    .then((response) => {
      console.log(response.data["balance"]);
    })
    .catch((error) => {
      console.error(error);
    });

https://flask-jwt-extended.readthedocs.io/en/stable/options/#jwt-cookie-csrf-protect suggests JWT_COOKIE_CSRF_PROTECT should be always True in production, so I cannot keep it False then https://flask-jwt-extended.readthedocs.io/en/stable/options/#jwt-cookie-csrf-protect建议 JWT_COOKIE_CSRF_PROTECT 在生产中应该始终为真,所以我不能保持它为假

Try to debug the request by examining headers.尝试通过检查标头来调试请求。 If you are sending requests from the browser, you can use any of Dev Tools (Chrome for example).如果您从浏览器发送请求,您可以使用任何开发工具(例如 Chrome)。 Take a look at the Network tab, look for your POST request, find out which cookies are sent.查看“网络”选项卡,查找您的 POST 请求,找出发送了哪些 cookies。

If you can't find CSRF token in the request then you should pass it from the backend to the frontend and keep it in cookies storage.如果您在请求中找不到 CSRF 令牌,那么您应该将它从后端传递到前端并将其保存在 cookies 存储中。

you can add csrf exception for request.您可以为请求添加 csrf 异常。

or follow:- https://flask-jwt-extended.readthedocs.io/en/3.0.0_release/tokens_in_cookies/或关注:- https://flask-jwt-extended.readthedocs.io/en/3.0.0_release/tokens_in_cookies/

After whole morning having trouble with this I realized CSRF token is only read from request headers as seen here: https://flask-jwt-extended.readthedocs.io/en/stable/_modules/flask_jwt_extended/view_decorators/ not from cookies, so in Vue you need to manually append this header to your requests.整个上午都遇到了这个问题后,我意识到 CSRF 令牌只能从请求标头中读取,如下所示: https://flask-jwt-extended.readthedocs.io/en/stable/_modules/flask_jwt_extended/view_decorators/而不是来自 cookies,所以在 Vue 中你需要手动 append 这个 header 到你的请求。

Relevant source code to add to your flask app and to your Vue app:添加到您的 flask 应用程序和您的 Vue 应用程序的相关源代码:

In flask app:在 flask 应用程序中:

app.config['JWT_ACCESS_CSRF_HEADER_NAME'] = "X-CSRF-TOKEN"
app.config['JWT_REFRESH_CSRF_HEADER_NAME'] = "X-CSRF-REFRESH-TOKEN"
app.config['JWT_CSRF_IN_COOKIES'] = False

In your flask app login function:在您的 flask 应用程序登录 function 中:

from flask_jwt_extended import (
jwt_required, create_access_token,
jwt_refresh_token_required, create_refresh_token,
get_jwt_identity, set_access_cookies,
set_refresh_cookies, get_raw_jwt, get_csrf_token
)

new_token = create_access_token(identity=current_user.id, fresh=False)
new_refresh_token=create_refresh_token(identity=current_user.id)
response = jsonify({
    'data': {
        'message':'Ok',
        'type': 'user',
        'id': current_user.id,
        'meta': {
            'accessToken': new_token,
            'access_csrf_token': get_csrf_token(new_token),
            'refreshToken': new_refresh_token,
            'refresh_csrf_token': get_csrf_token(new_refresh_token)
        }
    }
})
set_refresh_cookies(response, new_refresh_token)
set_access_cookies(response, new_token)
return (response)

In your Vue app in your login fuction "edit according if you use or not refresh token logic":在你的 Vue 应用程序中,你的登录功能“根据你是否使用刷新令牌逻辑进行编辑”:

axios.defaults.headers.common['X-CSRF-TOKEN']=response.data.data.meta.access_csrf_token
axios.defaults.headers.common['X-CSRF-REFRESH-TOKEN']=response.data.data.meta.refresh_csrf_token

And lastly do the same in yout Vue TokenRefreshPlugin or the method you use最后在你的 Vue TokenRefreshPlugin 或你使用的方法中做同样的事情

I guess there are more approaches like getting the CSRF headers from the cookies, but this one seems to work for me for now at least.我想还有更多方法,比如从 cookies 获取 CSRF 标头,但至少现在这个似乎对我有用。 The important point is adding this headers manually in Vue requests, because using axios.defaults.withCredentials = true is not enough.重点是在 Vue 请求中手动添加此标头,因为使用 axios.defaults.withCredentials = true 是不够的。

Also check header includes csrf token in the requests as akdev suggests.还要检查 header 是否按照 akdev 的建议在请求中包含 csrf 令牌。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM