有没有一种方法可以使用Access-Control-Allow-Origin标头允许多个跨域?

我知道* ,但是它太开放了。 我真的只想允许几个域名。

例如,如下所示:

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

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

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


#1楼

这对我有用:

SetEnvIf Origin "^http(s)?://(.+\.)?(domain\.example|domain2\.example)$" origin_is=$0
Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is

当放入.htaccess ,它将肯定起作用。


#2楼

如果它与Nginx匹配您的域,请按照以下方法回显Origin头,如果您想为一个字体提供多个子域,这很有用:

location /fonts {# this will echo back the origin headerif ($http_origin ~ "example.org$") {add_header "Access-Control-Allow-Origin" $http_origin;}
}

#3楼

也许我错了,但是据我所知, 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

因此,我认为可以接受不同的来历,并且应该将它们分开


#4楼

这是我为AJAX请求的PHP应用程序所做的工作

$request_headers        = apache_request_headers();
$http_origin            = $request_headers['Origin'];
$allowed_http_origins   = array("http://myDumbDomain.example"   ,"http://anotherDumbDomain.example"  ,"http://localhost"  ,);
if (in_array($http_origin, $allowed_http_origins)){  @header("Access-Control-Allow-Origin: " . $http_origin);
}

如果我的服务器允许$http_origin请求的来源,则将$http_origin本身作为Access-Control-Allow-Origin标头的值返回,而不是返回*通配符。


#5楼

并非所有浏览器都使用HTTP_ORIGIN。 HTTP_ORIGIN的安全性如何? 对我来说,它在FF中是空的。
我有允许访问我的站点的站点通过站点ID发送,然后检查数据库中具有该ID的记录并获得SITE_URL列值(www.yoursite.com)。

header('Access-Control-Allow-Origin: http://'.$row['SITE_URL']);

即使通过有效的站点ID发送,该请求也必须来自与该站点ID关联的数据库中列出的域。


#6楼

匹配子域的PHP代码示例。

if( preg_match("/http:\/\/(.*?)\.yourdomain.example/", $_SERVER['HTTP_ORIGIN'], $matches )) {$theMatch = $matches[0];header('Access-Control-Allow-Origin: ' . $theMatch);
}

#7楼

听起来,推荐的方法是让服务器从客户端读取Origin标头,然后将其与您希望允许的域列表进行比较,如果匹配,则将Origin标头的值回传给客户端作为响应中的Access-Control-Allow-Origin标头。

使用.htaccess您可以这样操作:

# ----------------------------------------------------------------------
# Allow loading of external fonts
# ----------------------------------------------------------------------
<FilesMatch "\.(ttf|otf|eot|woff|woff2)$"><IfModule mod_headers.c>SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.example|dev02.otherdomain.example)$" AccessControlAllowOrigin=$0Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOriginHeader merge Vary Origin</IfModule>
</FilesMatch>

#8楼

Google关于通过SSL投放广告和RFC本身的语法的支持答案似乎表明您可以用空格分隔URL。 不确定在不同的浏览器中对此的支持程度如何。


#9楼

对于多个域,请在.htaccess

<IfModule mod_headers.c>SetEnvIf Origin "http(s)?://(www\.)?(domain1.example|domain2.example)$" AccessControlAllowOrigin=$0$1Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOriginHeader set Access-Control-Allow-Credentials true
</IfModule>

#10楼

您应该意识到一个缺点:一旦将文件外包给CDN(或任何其他不允许脚本的服务器),或者文件缓存在代理服务器上,就会基于“来源”更改响应请求标头将不起作用。


#11楼

如果您在字体方面遇到麻烦,请使用:

<FilesMatch "\.(ttf|ttc|otf|eot|woff)$"><IfModule mod_headers>Header set Access-Control-Allow-Origin "*"</IfModule>
</FilesMatch>

#12楼

对于Nginx用户,允许多个域的CORS。 我喜欢@marshall的示例,尽管他的答案仅匹配一个域。 为了匹配域和子域的列表,此正则表达式使使用字体更加容易:

location ~* \.(?:ttf|ttc|otf|eot|woff|woff2)$ {if ( $http_origin ~* (https?://(.+\.)?(domain1|domain2|domain3)\.(?:me|co|com)$) ) {add_header "Access-Control-Allow-Origin" "$http_origin";}
}

这只会回显与给定域列表匹配的“ Access-Control-Allow-Origin”标头。


#13楼

我努力将其设置为运行HTTPS的域,所以我想我会分享解决方案。 我在httpd.conf文件中使用了以下指令:

    <FilesMatch "\.(ttf|otf|eot|woff)$">SetEnvIf Origin "^http(s)?://(.+\.)?example\.com$" AccessControlAllowOrigin=$0Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin</FilesMatch>

example.com更改为您的域名。 将其添加到httpd.conf文件的<VirtualHost xxxx:xx>内部。 请注意,如果您的VirtualHost具有端口后缀(例如:80 ),那么此指令将不适用于HTTPS,因此您还需要转到/ etc / apache2 / sites-available / default-ssl并在其中添加相同的指令文件,位于<VirtualHost _default_:443>部分中。

配置文件更新后,您将需要在终端中运行以下命令:

a2enmod headers
sudo service apache2 reload

#14楼

这是针对Apache的扩展选项,其中包括一些最新的和计划的字体定义:

<FilesMatch "\.(ttf|otf|eot|woff|woff2|sfnt|svg)$"><IfModule mod_headers.c>SetEnvIf Origin "^http(s)?://(.+\.)?(domainname1|domainname2|domainname3)\.(?:com|net|org)$" AccessControlAllowOrigin=$0$1$2Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOriginHeader set Access-Control-Allow-Credentials true</IfModule>
</FilesMatch>

#15楼

我们也可以在Asp.net应用程序的Global.asax文件中进行设置。

protected void Application_BeginRequest(object sender, EventArgs e){// enable CORSHttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "https://www.youtube.com");}

#16楼

对于安装了URL Rewrite 2.0模块的IIS 7.5+,请参见此答案


#17楼

这是基于yesthatguy的答案的Java Web应用程序解决方案。

我正在使用Jersey REST 1.x

配置web.xml以了解Jersey REST和CORSResponseFilter

 <!-- Jersey REST config --><servlet>    <servlet-name>JAX-RS Servlet</servlet-name><servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class><init-param> <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name><param-value>true</param-value></init-param><init-param><param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name><param-value>com.your.package.CORSResponseFilter</param-value></init-param>   <init-param><param-name>com.sun.jersey.config.property.packages</param-name><param-value>com.your.package</param-value></init-param>        <load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>JAX-RS Servlet</servlet-name><url-pattern>/ws/*</url-pattern></servlet-mapping>

这是CORSResponseFilter的代码

import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerResponse;
import com.sun.jersey.spi.container.ContainerResponseFilter;public class CORSResponseFilter implements ContainerResponseFilter{@Override
public ContainerResponse filter(ContainerRequest request,ContainerResponse response) {String[] allowDomain = {"http://localhost:9000","https://my.domain.example"};Set<String> allowedOrigins = new HashSet<String>(Arrays.asList (allowDomain));                  String originHeader = request.getHeaderValue("Origin");if(allowedOrigins.contains(originHeader)) {response.getHttpHeaders().add("Access-Control-Allow-Origin", originHeader);response.getHttpHeaders().add("Access-Control-Allow-Headers","origin, content-type, accept, authorization");response.getHttpHeaders().add("Access-Control-Allow-Credentials", "true");response.getHttpHeaders().add("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS, HEAD");}return response;
}}

#18楼

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

我的Nginx配置的相关部分:

if ($http_origin ~* (https?://.*\.mydomain.example(:[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';
}

#19楼

在Django中还有一个答案。 为了有一个视图,允许来自多个域的CORS,这是我的代码:

def my_view(request):if 'HTTP_ORIGIN' in request.META.keys() and request.META['HTTP_ORIGIN'] in ['http://allowed-unsecure-domain.com', 'https://allowed-secure-domain.com', ...]:response = my_view_response() # Create your desired response data: JsonResponse, HttpResponse...# Then add CORS headers for access from deliveryresponse["Access-Control-Allow-Origin"] = request.META['HTTP_ORIGIN']response["Access-Control-Allow-Methods"] = "GET" # "GET, POST, PUT, DELETE, OPTIONS, HEAD"response["Access-Control-Max-Age"] = "1000"  response["Access-Control-Allow-Headers"] = "*"  return response

#20楼

为了促进ASMX服务的多域访问,我在global.asax文件中创建了以下功能:

protected void Application_BeginRequest(object sender, EventArgs e)
{string CORSServices = "/account.asmx|/account2.asmx";if (CORSServices.IndexOf(HttpContext.Current.Request.Url.AbsolutePath) > -1){string allowedDomains = "http://xxx.yyy.example|http://aaa.bbb.example";if(allowedDomains.IndexOf(HttpContext.Current.Request.Headers["Origin"]) > -1)HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", HttpContext.Current.Request.Headers["Origin"]);if(HttpContext.Current.Request.HttpMethod == "OPTIONS")HttpContext.Current.Response.End();}
}

这也允许CORS处理OPTIONS动词。


#21楼

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

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

发送

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

在Apache上,可以使用mod_headers和以下语法在httpd.conf <VirtualHost>部分或.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作为第一个参数。


#22楼

如果您尝试了许多像我这样的代码示例,以使其可以使用CORS进行工作,那么值得一提的是,您必须先清除缓存才能尝试它是否真正起作用,这类似于像仍然存在旧图像的问题,即使它仍然存在。在服务器上删除(因为它仍保存在缓存中)。

例如,在Google Chrome浏览器中按CTRL + SHIFT + DEL即可删除缓存。

这在尝试了许多纯.htaccess解决方案后帮助我使用了这段代码,这似乎是唯一.htaccess方法(至少对我而言):

    Header add Access-Control-Allow-Origin "http://google.com"Header add Access-Control-Allow-Headers "authorization, origin, user-token, x-requested-with, content-type"Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"<FilesMatch "\.(ttf|otf|eot|woff)$"><IfModule mod_headers.c>SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.com|dev02.otherdomain.net)$" AccessControlAllowOrigin=$0Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin</IfModule></FilesMatch>

还要注意,许多解决方案都说必须键入Header set ...但这是Header add ... ,这一点已经很普遍了。 希望这可以像我一样帮助几个小时来遇到同样麻烦的人。


#23楼

为了对.NET应用程序进行相当简单的复制/粘贴,我编写了此代码,以便从global.asax文件中启用CORS。 该代码遵循当前接受的答案中给出的建议,将请求中给出的任何原点返回到响应中。 这有效地实现了“ *”而不使用它。

这样做的原因是,它启用了多个其他CORS功能 ,包括发送“ withCredentials”属性设置为“ true”的AJAX XMLHttpRequest的功能。

void Application_BeginRequest(object sender, EventArgs e)
{if (Request.HttpMethod == "OPTIONS"){Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");Response.AddHeader("Access-Control-Max-Age", "1728000");Response.End();}else{Response.AddHeader("Access-Control-Allow-Credentials", "true");if (Request.Headers["Origin"] != null)Response.AddHeader("Access-Control-Allow-Origin" , Request.Headers["Origin"]);elseResponse.AddHeader("Access-Control-Allow-Origin" , "*");}
}

#24楼

一种更灵活的方法是使用Apache 2.4的表达式。 您可以匹配域,路径以及几乎所有其他请求变量。 尽管发送的响应始终为* ,但接收到它的唯一请求者还是满足要求的请求者。 在表达式中使用Origin (或任何其他)请求标头会导致Apache自动将其合并到Vary响应标头中,这样响应就不会在其他源中重复使用。

<IfModule mod_headers.c><If "%{HTTP:Host} =~ /\\bcdndomain\\.example$/i && %{HTTP:Origin} =~ /\\bmaindomain\\.example$/i">Header set Access-Control-Allow-Origin "*"</If>
</IfModule>

#25楼

对于ExpressJS应用程序,您可以使用:

app.use((req, res, next) => {const corsWhitelist = ['https://domain1.example','https://domain2.example','https://domain3.example'];if (corsWhitelist.indexOf(req.headers.origin) !== -1) {res.header('Access-Control-Allow-Origin', req.headers.origin);res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');}next();
});

#26楼

下面的答案特定于C#,但该概念应适用于所有不同的平台。

要允许来自Web api的跨源请求,您需要允许对应用程序的Option请求,并在控制器级别添加以下注释。

[EnableCors(UrlString,Header,Method)]现在,原点只能以字符串形式传递。 因此,如果您要在请求中传递多个URL,则将其作为逗号分隔值传递。

UrlString =“ https://a.hello.com,https://b.hello.com ”


#27楼

Access-Control-Allow-Origin标头只能指定一个原点。 但是您可以根据要求在响应中设置原点。 同样不要忘记设置Vary标头。 在PHP中,我将执行以下操作:

    /*** Enable CORS for the passed origins.* Adds the Access-Control-Allow-Origin header to the response with the origin that matched the one in the request.* @param array $origins* @return string|null returns the matched origin or null*/function allowOrigins($origins){$val = $_SERVER['HTTP_ORIGIN'] ?? null;if (in_array($val, $origins, true)) {header('Access-Control-Allow-Origin: '.$val);header('Vary: Origin');return $val;}return null;}if (allowOrigins(['http://localhost', 'https://localhost'])) {echo your response here, e.g. token}

#28楼

我对woff-fonts有同样的问题,多个子域必须具有访问权限。 为了允许子域,我在httpd.conf中添加了以下内容:

SetEnvIf Origin "^(.*\.example\.com)$" ORIGIN_SUB_DOMAIN=$1
<FilesMatch "\.woff$">Header set Access-Control-Allow-Origin "%{ORIGIN_SUB_DOMAIN}e" env=ORIGIN_SUB_DOMAIN
</FilesMatch>

对于多个域,您可以只在SetEnvIf更改正则表达式。


#29楼

我在PHP中使用的另一个解决方案:

$http_origin = $_SERVER['HTTP_ORIGIN'];if ($http_origin == "http://www.domain1.com" || $http_origin == "http://www.domain2.com" || $http_origin == "http://www.domain3.com")
{  header("Access-Control-Allow-Origin: $http_origin");
}

访问控制允许原始多个域?相关推荐

  1. 解决cookie跨域访问

    v一.前言 随着项目模块越来越多,很多模块现在都是独立部署.模块之间的交流有时可能会通过cookie来完成.比如说门户和应用,分别部署在不同的机器或者web容器中,假如用户登陆之后会在浏览器客户端写入 ...

  2. asp 退出登录修改cookie能进入后台_深入浅出让你理解跨域与SSO单点登录原理与技术...

    一:SSO体系结构 SSO SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他应用 ...

  3. 深入理解跨域SSO单点登录原理与技术

    文章目录 1 SSO体系结构 1.1 SSO 1.2 体系结构 1.3 Token(令牌) 1.4 同域SSO原理分析 token的生成 token过期移除 认证流程 1.5 跨域SSO原理分析 分析 ...

  4. java单点登录跨域_深入浅出让你理解跨域与SSO单点登录原理与技术

    原标题:深入浅出让你理解跨域与SSO单点登录原理与技术 一:SSO体系结构 SSO SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互 ...

  5. 跨域?拒绝说概念(内含demo)

    文章列出解决方案以及对应的demo,拒绝说概念,不在稀里糊涂. 什么情况出现跨域? 协议不同 域名不同 端口不同 跨域解决方案 1.同一个主域下不同子域之间的跨域请求 - document.domai ...

  6. linux DNS辅域

    1.确认包安装 2配置文档的两个目录要知道: /etc/named.conf 配置服务的 /var/named/ 做链接的目录 /var/named/chroot/var/named 原始目录 主域: ...

  7. SpringMVC+RestFul详细示例实战教程(实现跨域访问)

    一.理解 REST REST(Representational State Transfer),中文翻译叫"表述性状态转移".是 Roy Thomas Fielding 在他200 ...

  8. 时代亿信 文件共享访问控制网关

    1.1  产品简介 随着企业内网建设的不断完善,企业对各种文件服务器的需求越来越大,这些服务器为不同的用户提供文件共享服务,其中不乏有些机密数据文件,如各种工程.建筑.机械设备的图纸或程序源码等,这些 ...

  9. 牛红红的日记(平平无奇拿下域控)

    牛红红的日记(平平无奇拿下域控) 注:本文首发地址:https://www.sec-in.com 文章作者为-句芒安全实验室-成员之一,欢迎微信搜索关注我们. 一.引文 x年x月x日 晴 我是一只牛, ...

最新文章

  1. class instance java_[Java] Java instanceof 和 Class.isInstance()区别与应用
  2. html头文件设置常用之meta设置缓存
  3. BurpSuite pro v2.0.11版
  4. iOS本地化项目上传到gitHub
  5. Function One
  6. Apache Payara:让我们加密
  7. 学习笔记5-C语言-数组
  8. django 修改html无变化,Django Pycharm 修改html后立即刷新页面
  9. docker存储--理解镜像文件系统aufs/device mapper、主机存储共享、容器间存储共享、分布式存储Flocker
  10. Mysql 的utf8和utf8mb4
  11. 医院耗材管理系统开发_15
  12. Multi-task中的多任务loss平衡问题
  13. CSS盒子模型、浮动+例子分析
  14. (附源码)Python学生兼职平台系统 毕业设计 160938
  15. 解决crontab定时任务多次执行
  16. 最近的一些杂感-20220107
  17. Repulsion Loss: Detecting Pedestrians in a Crowd 详解(遮挡下的行人检测)
  18. Flutter 启动外部浏览器
  19. Linux服务器修改FTP密码
  20. 机械硬盘突然消失的解决办法(亲测有用)

热门文章

  1. Service Intent must be explicit
  2. 关于Unicode,字符集,字符编码
  3. Jquery mobile技术咖们走进来瞧瞧吧
  4. php 大牛生小牛,C#算法之关于大牛生小牛的问题
  5. Android之对资源图片进行比例缩放
  6. 使用Storm实现WordSum
  7. Android 之问题集锦
  8. swift_021(Swift 的方法)
  9. excel合并多个工作表_如何快速的合并多个 Excel 工作簿至一个工作簿中的工作表?...
  10. C++设计模式 之 “组件协作”模式:Template Method、Strategy、Observer