访问控制允许来源多个来源域?

有没有办法使用Access-Control-Allow-Origin头允许多个跨域?

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

举个例子,像这样的:

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

我已经尝试了上面的代码,但似乎并没有在Firefox中工作。

是否可以指定多个域名,还是我坚持一个?

听起来像推荐的方法是让你的服务器从客户端读取Origin标头,将它与你想要允许的域列表进行比较,如果匹配,则将Origin标头的值回显到客户端作为响应中的Access-Control-Allow-Origin标头。

.htaccess你可以这样做:

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

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

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

这对我工作:

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

input.htaccess

它会肯定的工作。

干杯!!

我有与woff字体相同的问题,多个子域必须有权访问。 为了允许子域名,我在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的正则expression式。

以下是如何将Origin头文件与Nginx相匹配的情况,如果您想要为多个子字段提供字体,则可以使用这种方法:

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

这是我为一个正在被AJAX请求的PHP应用程序所做的

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

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

对于多个域,在你的.htaccess中:

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

有一个缺点,你应该知道:只要你外部文件到CDN(或任何其他服务器不允许脚本),或者如果你的文件caching在代理上,改变基于“起源”请求标题将不起作用。

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

对于Nginx用户来说,允许多个域的CORS。 我喜欢@ marshall的例子,虽然他的anwers只匹配一个域名。 要匹配域和子域的列表,这个正则expression式使得它可以轻松地处理字体:

 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”标题。

根据yesthatguy的回答,这里有一个针对Java的解决scheme。 欲了解更多信息,请访问http://patrickgrimard.com/2013/12/12/cross-origin-resource-sharing-cors-requests-with-spring-mvc/

 @Provider public class CORSResponseFilter implements ContainerResponseFilter{ @Override public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { String[] allowDomain = {"http://localhost:9000","https://my.domain.com"}; 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; } } 

也许我错了..但据我所见,Access-Control-Allow-Origin有一个“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 

从这个angular度来说,我认为不同的起源是被承认的,应该是空间分离的

我努力设置这个运行HTTPS的域名,所以我想我会分享解决scheme。 我在我的httpd.conf文件中使用了以下指令:

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

example.com更改为您的域名。 在你的httpd.conf文件中join<VirtualHost xxxx:xx> 。 注意,如果你的VirtualHost有一个端口后缀(例如:80 ),那么这个指令不适用于HTTPS,所以你还需要去/ etc / apache2 / sites-available / default-ssl并添加相同的指令文件,在<VirtualHost _default_:443>部分内。

一旦configuration文件被更新,您将需要在terminal中运行以下命令:

 a2enmod headers sudo service apache2 reload 

如果您遇到字体问题,请使用:

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

如上所述,Access-Control-Allow-Origin应该是唯一的,如果您在CDN后面,则应该将Vary设置为Origin。 我的Nginx conf的相关部分:

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

答案似乎是不止一次地使用标题。 那就是,而不是发送

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

发送

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

在Apache上,您可以使用mod_headershttpd.conf <VirtualHost>部分或.htaccess文件中mod_headersmod_headers并使用以下语法:

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

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

所有浏览器都不使用HTTP_ORIGIN。 HTTP_ORIGIN有多安全? 对我来说,在FF中是空的。
我有我允许访问我的网站的网站发送一个网站ID,然后检查我的数据库与该ID的logging,并获得SITE_URL列值(www.yoursite.com)。

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

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

还有一个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 delivery response["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 

Google 对SSL服务广告和RFC中语法的支持答案似乎表明您可以对URL进行空格分隔。 不知道这是不同的浏览器有多好的支持。

下面是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$2 Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin Header set Access-Control-Allow-Credentials true </IfModule> </FilesMatch> 

为了方便ASMX服务的多域访问,我在global.asax文件中创build了这个函数:

 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.com|http://aaa.bbb.com"; 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动词。

用于匹配子域的PHP代码示例。

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

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

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

如果您尝试使用像CORS这样的代码示例来使其工作,那么值得一提的是,您必须首先清除caching,然后尝试是否实际运行,类似于旧图像仍然存在的问题,即使它是在服务器上删除(因为它仍然保存在caching中)。

例如在Chrome浏览器中按CTRL + SHIFT + DEL删除caching。

这帮助我在尝试了许多纯粹的.htaccess解决scheme之后使用了这个代码,这似乎是唯一可行的(至less对我来说):

  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=$0 Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin </IfModule> </FilesMatch> 

另外请注意,很多解决scheme都说你必须inputHeader set ...但它是Header add ... 希望这能帮助像我这样几个小时有同样麻烦的人。