cors 子域失败
Posted
技术标签:
【中文标题】cors 子域失败【英文标题】:cors failing for subdomains 【发布时间】:2019-09-07 18:30:18 【问题描述】:CORS 在域和子域中无法正常工作。 我有一个托管在 https://api.example.com 的 NodeJS 服务器 我有两个 ReactJS 客户端
客户端 1。https://example.com
客户端 2。https://subdomain.example.com
我已将客户端 1 配置为强制使用 www,以便客户端 1 使用单一来源。 当我打开 Clien1 时,它工作正常。 当我打开 Client2 时,出现
从源“https://subdomain.example.com”访问“https://api.example.com/someAPI”处的 XMLHttpRequest 已被 CORS 策略阻止:“Access-Control-Allow-Origin”标头的值“https://www.example.com”不等于提供的来源
当我按 Ctrl+F5 时它工作正常,但之后如果我刷新 Client1 则错误出现在 Client1 上
从源“https://www.example.com”访问“https://api.example.com/someAPI”处的 XMLHttpRequest 已被 CORS 策略阻止:“Access-Control-Allow-Origin”标头的值“https://subdomain.example.com”不等于提供的来源。
现在,当我在 Client1 上按 Ctrl+F5 时,它工作正常,但同样的错误出现在 Client2 上。
我的nodeJS服务器配置如下
var whitelist = ['https://www.example.com', 'https://subdomain.example.com'];
getCorsCoptions(req, callback)
var getOriginValue = () =>
if (whitelist.indexOf(req.header('origin')) !== -1)
return true;
else
log.error(__filename, 'Not allowed by CORS', origin);
return false;
var corsOptions =
origin: getOriginValue(),
methods: ['GET', 'POST'],
credentials: true,
preflightContinue: false,,
allowedHeaders:["Content-Type","X-Requested-With","X-HTTP-Method-Override","Accept"]
callback(null, corsOptions)
app.use('*', cors(this.getCorsCoptions));
app.options('*', cors(this.getCorsCoptions));
我在 React Client 端使用 axios 如下
get(url: string)
return Axios.get(url,
withCredentials: true
).then((res: any) =>
if (res)
return res.data;
return ;
);
post(url: string, data: any)
let requestHeaders = 'Content-Type': 'application/json' ;
return Axios.post(url, data,
headers: requestHeaders
, withCredentials: true
).then((res: any) =>
if (res)
return res.data;
return ;
);
【问题讨论】:
你在服务器上使用express
吗?
是的,在服务器上使用 express
我已经发布了答案。尝试将您的 corsOptions.origin 设置为您想要工作的 URL 字符串数组
不确定,但听起来您可能想尝试在响应中添加 Vary: Origin
响应标头。请参阅***.com/a/46735000/441757 和***.com/a/46067554/441757 的答案并查看developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary
【参考方案1】:
我找到了解决这个问题的方法。浏览器正在缓存源。 通过在响应中添加以下标头解决了这个问题
Cache-Control: no-store,no-cache,must-revalidate
我还添加了Vary: Origin
,但我认为它并没有解决问题
我管理 cors 如下
var whitelist = ['https://www.example.com', 'https://subdomain.example.com'];
router.all("*", (req, res, next) =>
var origin = req.headers.origin;
if (whitelist.indexOf(origin) != -1)
res.header("Access-Control-Allow-Origin", origin);
res.header("Access-Control-Allow-Headers", ["Content-Type","X-Requested-With","X-HTTP-Method-Override","Accept"]);
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Methods", "GET,POST");
res.header("Cache-Control", "no-store,no-cache,must-revalidate");
res.header("Vary", "Origin");
if (req.method === "OPTIONS")
res.status(200).send("");
return;
next();
);
路由器在哪里 express.Router()
我希望有人觉得这很有帮助。
【讨论】:
【参考方案2】:这是因为你正在调用你的函数,你只需要将它传递给中间件
var corsOptions =
origin: getOriginValue, // Not origin: getOriginValue()<-no parens,
methods: ['GET', 'POST'],
credentials: true,
preflightContinue: false,,
allowedHeaders:["Content-Type","X-Requested-With","X-HTTP-Method-Override","Accept"]
【讨论】:
你注意到了一个正确的观点,但这并不能解决我的问题【参考方案3】:您似乎在使用 express。根据他们的文档,您可以将 origin 设置为字符串数组或 RegExp,这应该允许您想要的来源。
https://expressjs.com/en/resources/middleware/cors.htmlorigin:配置 Access-Control-Allow-Origin CORS 标头。 可能的值:
数组 - 将原点设置为有效原点的数组。 每个来源可以是字符串或正则表达式。例如 ["http://example1.com", /.example2.com$/] 将接受任何请求 来自“http://example1.com”或来自“example2.com”的子域。
基于此,将getOriginValue()
更新为以下内容可能对您有用:
var getOriginValue = () =>
if (whitelist.indexOf(req.header('origin')) !== -1)
return whitelist; // Return array of strings
else
log.error(__filename, 'Not allowed by CORS', origin);
return false;
【讨论】:
以上是关于cors 子域失败的主要内容,如果未能解决你的问题,请参考以下文章