Access-Control-Allow-Origin Múltiplos Domínios de Origem?

Existe uma maneira de permitir vários domínios cruzados usando o header Access-Control-Allow-Origin ?

Estou ciente do * , mas é muito aberto. Eu realmente quero permitir apenas alguns domínios.

Por exemplo, algo como isto:

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

Eu tentei o código acima, mas parece não funcionar no Firefox.

É possível especificar vários domínios ou estou preso com apenas um?

Parece que a maneira recomendada de fazer isso é fazer com que o servidor leia o header Origem do cliente, compare com a lista de domínios que você gostaria de permitir e, se corresponder, faça o eco do valor do header Origin volta para o cliente como o header Access-Control-Allow-Origin na resposta.

Com .htaccess você pode fazer assim:

 # ---------------------------------------------------------------------- # Allow loading of external fonts # ----------------------------------------------------------------------   SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.example|dev02.otherdomain.example)$" AccessControlAllowOrigin=$0 Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin Header merge Vary Origin   

Outra solução que estou usando no 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"); } 

Isso funcionou para mim:

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

Quando colocado em .htaccess , funcionará com certeza.

Eu tive o mesmo problema com fonts woff, vários subdomínios tinham que ter access. Para permitir subdomínios eu adicionei algo assim ao meu httpd.conf:

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

Para vários domínios, você poderia apenas alterar o regex em SetEnvIf .

Veja como fazer o eco do header de origem de volta, se ele corresponder ao seu domínio com o Nginx. Isso será útil se você quiser exibir uma fonte com vários subdomínios:

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

Aqui está o que eu fiz para uma aplicação PHP que está sendo solicitada pelo AJAX

 $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); } 

Se a origem solicitante for permitida pelo meu servidor, retorne o $http_origin como valor do header Access-Control-Allow-Origin vez de retornar um caractere curinga * .

Há uma desvantagem da qual você deve estar ciente: assim que você terceiriza os arquivos para um CDN (ou qualquer outro servidor que não permita scripts) ou se seus arquivos estão armazenados em cache em um proxy, alterando a resposta com base em ‘Origem’ o header da solicitação não funcionará.

Para vários domínios, no seu .htaccess :

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

Para o IIS 7.5+ com o módulo URL Rewrite 2.0 instalado, consulte esta resposta

Para usuários do Nginx, permitir CORS para vários domínios. Eu gosto do exemplo do @marshall, embora seus anwers correspondam apenas a um domínio. Para corresponder a uma lista de domínio e subdomínio, este regex facilita o trabalho com fonts:

 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"; } } 

Isso só ecoará os headers “Access-Control-Allow-Origin” que correspondem à lista de domínios fornecida.

Aqui está uma solução para o aplicativo da web Java, com base na resposta do yesthatguy.

Estou usando o Jersey REST 1.x

Configure o web.xml para estar ciente do Jersey REST e do CORSResponseFilter

    JAX-RS Servlet com.sun.jersey.spi.container.servlet.ServletContainer  com.sun.jersey.api.json.POJOMappingFeature true   com.sun.jersey.spi.container.ContainerResponseFilters com.your.package.CORSResponseFilter   com.sun.jersey.config.property.packages com.your.package  1   JAX-RS Servlet /ws/*  

Aqui está o código para o 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 allowedOrigins = new HashSet(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; } } 

Como mencionado acima, Access-Control-Allow-Origi n deve ser exclusivo e Vary deve ser definido como Origin se você estiver atrás de um CDN. Parte relevante da minha configuração 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'; } 

Talvez eu esteja errado, mas tanto quanto eu posso ver Access-Control-Allow-Origin tem uma "origin-list" como parâmetro.

Por definição, uma origin-list é:

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

E a partir disso, eu argumento que diferentes origens são admitidas e devem ser separadas por espaços .

Eu me esforcei para configurar isso em um domínio rodando HTTPS, então imaginei que compartilharia a solução. Eu usei a seguinte diretiva no meu arquivo httpd.conf :

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

Altere example.com para seu nome de domínio. Adicione isto dentro de em seu arquivo httpd.conf . Observe que se o seu VirtualHost tiver um sufixo de porta (por exemplo :80 ), esta diretiva não se aplicará a HTTPS, então você também precisará ir para / etc / apache2 / sites-available / default-ssl e adicionar a mesma diretiva arquivo, dentro da seção .

Quando os arquivos de configuração forem atualizados, você precisará executar os seguintes comandos no terminal:

 a2enmod headers sudo service apache2 reload 

Se você está tendo problemas com fonts, use:

   Header set Access-Control-Allow-Origin "*"   

HTTP_ORIGIN não é usado por todos os navegadores. Quão seguro é o HTTP_ORIGIN? Para mim, aparece vazio em FF.
Eu tenho os sites que permitem o access ao meu site enviar através de um ID do site, então eu verificar meu database para o registro com esse id e obter o valor da coluna SITE_URL (www.seusite.com).

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

Mesmo se o envio de um ID de site válido, a solicitação precisa ser do domínio listado no meu database associado a esse ID de site.

Aqui está uma opção expandida para o apache que inclui algumas das definições de fonte mais recentes e planejadas:

   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   

E mais uma resposta no Django. Para ter uma visão única, permita CORS de múltiplos domínios, aqui está o meu código:

 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 

Para facilitar o access de vários domínios para um serviço ASMX, criei esta function no arquivo 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(); } } 

Isso permite o tratamento CORS do verbo OPTIONS também.

A resposta de suporte do Google ao veicular anúncios sobre SSL e a gramática no próprio RFC parece indicar que você pode delimitar os URLs por espaço. Não tenho certeza de como isso é bem suportado em diferentes navegadores.

Se você tentar tantos exemplos de código como eu para fazê-lo funcionar usando CORS, vale a pena mencionar que você precisa limpar seu cache primeiro para tentar se realmente funciona, semelhante a problemas como quando imagens antigas ainda estão presentes, mesmo que seja excluído no servidor (porque ainda está salvo em seu cache).

Por exemplo, CTRL + SHIFT + DEL no Google Chrome para excluir seu cache.

Isso me ajudou a usar este código depois de tentar muitas soluções puras de .htaccess e isso pareceu o único funcionando (pelo menos para mim):

  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"   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   

Note também que é amplamente difundido que muitas soluções dizem que você tem que digitar Header set ... mas é Header add ... Espero que isso ajude alguém com os mesmos problemas por algumas horas agora como eu.

Para uma cópia / colagem bastante fácil para aplicativos .NET, eu escrevi isso para ativar o CORS de dentro de um arquivo global.asax. Este código segue o conselho dado na resposta aceita no momento, refletindo a origem de volta é dada na solicitação para a resposta. Isso efetivamente alcança ‘*’ sem usá-lo. A razão para isso é que ele habilita vários outros resources do CORS, incluindo a capacidade de enviar um AJAX XMLHttpRequest com o atributo ‘withCredentials’ definido como ‘true’.

 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"]); else Response.AddHeader("Access-Control-Allow-Origin" , "*"); } } 

Uma abordagem mais flexível é usar as expressões do Apache 2.4. Você pode comparar domínios, caminhos e praticamente todas as outras variables ​​de solicitação. Embora a resposta seja * para todos, os únicos solicitantes que recebem essa resposta são os que atendem aos requisitos de qualquer maneira.

   Header set Access-Control-Allow-Origin "*"   

Exemplo de código PHP para subdomínios correspondentes.

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

A resposta parece ser usar o header mais de uma vez. Isto é, ao invés de enviar

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

enviar

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

No Apache, você pode fazer isso em uma seção httpd.conf ou no arquivo .htaccess usando mod_headers e esta syntax:

 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" 

O truque é usar add vez de append como primeiro argumento.

Também podemos definir isso no arquivo Global.asax para o aplicativo Asp.net.

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