添加 JWT 授权标头后,CORS 无法工作

Posted

技术标签:

【中文标题】添加 JWT 授权标头后,CORS 无法工作【英文标题】:CORS fails to work once I add a JWT authorization header 【发布时间】:2020-01-09 04:02:37 【问题描述】:

我有一个 Flask 后端和一个 React 前端。 Flask 后端是一个与其他微服务通信的 API。在开发中,我的 React 前端在 localhost:3000 上运行,Flask 应用程序在 localhost:5000 上运行。 显然,这些是不同的端口,默认情况下会引发 CORS 错误。所以我添加了 Flask_CORS 并允许来自 localhost:3000 的流量。这可行,我现在可以处理 GET 和 POST 请求。

然后我将我的 Firebase 身份验证添加到前端。我收到一个 JWT,然后我想发送带有 ech API 请求的 JWT,以确保允许用户发出某些请求,这些请求将在 Flask 后端进行验证。

我将 token_id 添加到后端的 Axios 请求的标头中,但现在我收到以下错误:

localhost/:1 从源 'http://localhost:3000' 访问 XMLHttpRequest 在 'http://localhost:5000/items' 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:否 'Access-Control-Allow-请求的资源上存在 Origin' 标头。

当我检查网络选项卡时,我注意到没有 JWT 请求可以正常通过。标题内容见下文:

一般:

请求网址:http://localhost:5000/items 请求方法:GET 状态码:200 OK 远程地址:127.0.0.1:5000 推荐人政策:降级时无推荐人

响应标头:

Access-Control-Allow-Origin: http://localhost:3000 内容长度:37 内容类型:应用程序/json 日期:格林威治标准时间 2019 年 9 月 6 日星期五 09:10:10 服务器:Werkzeug/0.15.5 Python/3.7.4 变化:原产地

请求标头:

显示临时标题 接受:应用程序/json、文本/纯文本、/ 来源:http://localhost:3000 推荐人:http://localhost:3000/ Sec-Fetch-Mode:cors 用户代理:Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit/537.36(Khtml,如 Gecko)Chrome/76.0.3809.132 Safari/537.36

然后我只将 JWT 添加到 Axios 拦截器的授权标头配置中,现在请求失败,网络选项卡中出现以下标头:

一般: 请求网址:http://localhost:5000/items 请求方法:选项 状态码:200 OK 远程地址:127.0.0.1:5000 推荐人政策:降级时无推荐人 响应标头: 允许:POST、OPTIONS、HEAD、GET 内容长度:0 内容类型:文本/html; charset=utf-8 日期:格林威治标准时间 2019 年 9 月 6 日星期五 09:14:46 服务器:Werkzeug/0.15.5 Python/3.7.4 请求标头: 显示临时标题 访问控制请求标头:授权 访问控制请求方法:GET 来源:http://localhost:3000 推荐人:http://localhost:3000/ Sec-Fetch-Mode: no-cors 用户代理:Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit/537.36(KHTML,如 Gecko)Chrome/76.0.3809.132 Safari/537.36

我注意到,当添加授权标头时,Access-Control-Allow-Origin 消失了,而是出现了 Access-Control_Request-Headers。

前端感兴趣的代码如下

import axios from 'axios';
import * as firebase from "firebase/app";
import 'firebase/auth';

const instance = axios.create(
    baseURL: 'http://localhost:5000/',
);

instance.interceptors.request.use(config => 
    const id_token = firebase.auth().currentUser.getIdToken();
    config.headers =  Authorization: id_token; <---Commenting out this line works
    return config
, error => 
    return Promise.reject(error);
)
export default instance;

我不知道 CORS 在添加 JWT 后如何或为何无法工作。我怀疑这是因为一旦添加了 JWT,就会有一个飞行前请求。但是我在服务器端没有任何改变,所以我很困惑为什么服务器不会仅仅因为添加了 JWT 就提供合适的 lCORS 响应。

任何指针将不胜感激。

【问题讨论】:

顺便说一句:如果你使用 create-react-app,你可以在你的 package.json 文件中添加一个代理:link 【参考方案1】:

您可以在主文件顶部定义 CORS,它将允许所有 CORS 请求

from flask import Flask
from flask_cors import CORS, cross_origin

app = Flask(__name__)
CORS(app)

@app.route("/api/test")
def test_cors():
  return "CORS allowed"

【讨论】:

我使用的是装饰器语法:@cross_origin(origins ='*', expose_headers='Authorization')。不幸的是,它给出了相同的结果 您可以尝试添加 origins 和 support_credentials 吗? 你可以试试没有像上面这样的装饰器吗? 我从 CORS(app) 调用中取出了所有内容(即不是 app 以外的参数)。然后使用没有参数的装饰器(即@cross_origin())并且它正在工作。似乎将参数传递给 CORS() 会干扰某些事情。 很高兴听到这个消息,您也可以删除 @cross_origin,因为当您在文件顶部定义 CORS 时,它将应用您应用的所有路由,请参阅 official docs here!

以上是关于添加 JWT 授权标头后,CORS 无法工作的主要内容,如果未能解决你的问题,请参考以下文章

在 HTTP-Request 中使用 JWT 发送授权标头

如何在授权标头中将带有 fetch 和 cors 的 JWT 令牌发送到 Express 服务器?

使用 jwt 授权反应 js 在标头中添加授权时遇到问题?

添加授权标头时出现CORS错误

应用 jwt auth 包装器时,Flask-cors 包装器不起作用。

如何使用授权标头发出 GET CORS 请求