即使在 Flask 应用程序中启用了 CORS,也未设置 Cookie

问题描述 投票:0回答:2

请注意:像这样的问题有很多,但没有一个对我有用,这就是我问这个的原因。

我的 REST API 是一个 Flask 应用程序。我的

/login
端点使用 JWT 并在客户端的 cookie 中设置访问和刷新令牌。

我在

127.0.0.1:5000
上运行 Flask,在
127.0.0.1:8080
上运行前端。

后端代码

@auth.api(
    http_path='/login',
    http_method='POST',
)
def login(email, password):
    # ...
    access_token = create_access_token(identity=user.id, fresh=True, expires_delta=app.config['JWT_ACCESS_TOKEN_EXP'])
    refresh_token = create_refresh_token(identity=user.id, expires_delta=app.config['JWT_REFRESH_TOKEN_EXP'])

    resp = jsonify({'login': True})
    set_access_cookies(resp, access_token)
    set_refresh_cookies(resp, refresh_token)
    # ...
    return resp

我的应用程序启用了 CORS:

from flask_cors import CORS
# ...
cors = CORS()

def create_app():
    app = Flask(__name__)
    # ...
    cors.init_app(app)
    # ...
    return app

客户端代码

$.ajax({
    method: "POST",
    url: "http://127.0.0.1:5000/login",
    data: JSON.stringify({email: 'myemail', password: 'mypassword'}),
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function (data) {
        console.log('logged in!');
    }
});

问题

Firefox、Chrome 或 Edge 中均未设置 cookie。但是,当使用浏览器的开发工具时,我可以在响应标头中看到 cookie,但 Cookie 下的存储部分中没有显示任何内容。

我尝试了多种方法:

  • 在后端设置
    cors=CORS(supports_credentials=True)
    ,在前端设置
    xhrFields:{ withCredentials: true}
  • 在前端设置
    crossDomain: true
  • 确保浏览器设置没有阻止 cookie
  • 专门在
    127.0.0.1
    而不是
    localhost
  • 上运行

我的前端需要某种代理吗?一定有更简单的解决方案。

ajax flask cookies cross-domain
2个回答
2
投票

经过一番头痛之后,我终于明白出了什么问题了。这部分是我的错,但也是一个潜在的错误。

我正在使用

flask-jwt-extended
库进行 JWT 身份验证;有一些关于 JWT 的环境变量,其值在
set_access_cookies
函数中使用。

通常,您的 Flask 应用程序配置是存放这些变量的位置,但是,我选择使用单独的 .env 文件并从中加载环境变量。问题是,对于像

MY_VAR=False
这样的东西,
MY_VAR
会得到 字符串值“False”,而不是布尔标志。

这对于

JWT_COOKIE_SECURE
来说表现得特别差 - 该变量的值在
set_access_cookies
函数中使用,该函数本身对
set_cookie
对象使用
Request
函数 - 如果为 Secure 字段传递一个字符串,它会混淆 cookie,您的浏览器很可能会忽略它。

所以乱码 cookie 看起来像这样:

('Set-Cookie', 'access_token_cookie=yourtoken; Domain=localhost.example.com; Secure; HttpOnly; Path=/')

注意

Secure
字段是空的,而它应该是布尔值或根本不存在(如果为 false)。

我希望这有帮助!


0
投票

对于现在遇到此问题的其他人来说,接受的答案实际上并不完全正确。 问题不在于

Secure;
标志存在,它按预期工作,但对其作用存在误解。 如果设置了
Secure
标志,则意味着浏览器将仅通过 https 连接发送该 cookie。 这意味着如果您在项目中将
JWT_COOKIE_SECURE
设置为 true,将为浏览器设置 cookie,但如果您不使用 https,则不会发送它们。

解决方案是将其设置为 false,但这是一个坏主意,因为访问令牌随后会以未加密的方式发送并且很容易被盗,或者使用 https。

注意:出于某种原因,只有在发出跨源请求时才会出现这种情况(当我部署服务器时,会出现这种情况)。在本地主机上调试时,我从未遇到过这个问题,即使

JWT_COOKIE_SECURE
设置为 true 并且我没有使用 https。

© www.soinside.com 2019 - 2024. All rights reserved.