是否有一种方法允许多个跨域使用Access-Control-Allow-Origin头?

我知道*,但它太开放了。我只讲几个域。

举个例子,是这样的:

Access-Control-Allow-Origin: http://domain1.example, http://domain2.example

我已经尝试了上面的代码,但它似乎不能在Firefox中工作。

是否可以指定多个域,还是只能指定一个域?


当前回答

有一个缺点你应该知道:一旦你将文件外包到CDN(或任何其他不允许脚本的服务器),或者如果你的文件缓存在代理上,根据“Origin”请求头更改响应将不起作用。

其他回答

也许我错了,但据我所知,Access-Control-Allow-Origin有一个“origin-list”作为参数。

根据定义,origin-list为:

origin            = "origin" ":" 1*WSP [ "null" / origin-list ]
origin-list       = serialized-origin *( 1*WSP serialized-origin )
serialized-origin = scheme "://" host [ ":" port ]
                  ; <scheme>, <host>, <port> productions from RFC3986

由此,我认为不同的起源是被承认的,并且应该被空间分隔开。

答案似乎是多次使用头文件。也就是说,而不是发送

Access-Control-Allow-Origin: http://domain1.example, http://domain2.example, http://domain3.example

send

Access-Control-Allow-Origin: http://domain1.example
Access-Control-Allow-Origin: http://domain2.example
Access-Control-Allow-Origin: http://domain3.example

在Apache上,你可以在httpd.conf <VirtualHost> section或.htaccess文件中使用mod_headers和以下语法来实现:

Header add Access-Control-Allow-Origin "http://domain1.example"
Header add Access-Control-Allow-Origin "http://domain2.example"
Header add Access-Control-Allow-Origin "http://domain3.example"

诀窍是使用add而不是append作为第一个参数。

PHP代码:

$httpOrigin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : null;
if (in_array($httpOrigin, [
    'http://localhost:9000', // Co-worker dev-server
    'http://127.0.0.1:9001', // My dev-server
])) header("Access-Control-Allow-Origin: ${httpOrigin}");
header('Access-Control-Allow-Credentials: true');

如上所述,Access-Control-Allow-Origin应该是唯一的,如果您位于CDN(内容分发网络)后面,则应该将Vary设置为Origin。

Nginx配置的相关部分:

if ($http_origin ~* (https?://.*\.mydomain\.com(:[0-9]+)?)) {
  set $cors "true";
}
if ($http_origin ~* (https?://.*\.my-other-domain\.com(:[0-9]+)?)) {
  set $cors "true";
}

if ($cors = "true") {
  add_header 'Access-Control-Allow-Origin' "$http_origin";
  add_header 'X-Frame-Options' "ALLOW FROM $http_origin";
  add_header 'Access-Control-Allow-Credentials' 'true';
  add_header 'Vary' 'Origin';
}

AWS Lambda/ fire Gateway

有关如何在无服务器AWS Lambda和API网关上配置多个源的信息-尽管一个相当大的解决方案,但人们会觉得应该非常简单-请参阅这里:

https://stackoverflow.com/a/41708323/1624933


目前不可能在API Gateway中配置多个源,请参阅这里:https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html),但建议(在上面的回答中)是:

检查浏览器发送的Origin报头 在来源白名单上查一下 如果匹配,返回传入的Origin作为Access-Control-Allow-Origin头,否则返回占位符(默认Origin)。


简单的解决方案显然是可行的 所有(*)像这样:

exports.handler = async (event) => {
    const response = {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS
        },
        body: JSON.stringify([{

但是在API网关端做这件事可能会更好(见上面的第二个链接)。