Acesso-controle-permissão-origem vários domínios de origem?

1049

Existe uma maneira de permitir vários domínios cruzados usando o Access-Control-Allow-Origincabeçalho?

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

Como exemplo, algo como isto:

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

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

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

Thomas J Bradley
fonte
3
Usando o Firefox mais recente, nem os domínios separados por vírgulas nem os separados por espaço funcionaram. Combinar com uma lista de domínios e colocar um único host nos cabeçalhos ainda é uma segurança melhor e funciona corretamente.
Daniel W.
1
Se você está lutando com isso para HTTPS, encontrei uma solução .
Alex W
7
observação importante : permitir apenas domínios cretain noAccess-Control-Allow-Origincabeçalho não significa que outros domínios não possam acionar um método nesse nó de extremidade (por exemplo, método da API REST). Significa apenas que origens não permitidas não podem usar o resultado em javascript (o navegador garante isso). Para restringir o acesso a um nó de extremidade para domínios específicos, use um filtro de solicitação do servidor que, por exemplo, retorne HTTP 401 para domínios não permitidos.
klues
1
Você deve sempre acrescentar Vary: Origincabeçalho quando você quiser usar vários URLs, consulte: fetch.spec.whatwg.org/#cors-protocol-and-http-caches
Null

Respostas:

861

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

Com .htaccessvocê pode fazer assim:

# ----------------------------------------------------------------------
# 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=$0
        Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
        Header merge Vary Origin
    </IfModule>
</FilesMatch>
yesthatguy
fonte
41
Isso corresponde ao que o W3C sugere - w3.org/TR/cors/#access-control-allow-origin-response-hea #
Simon B.
153
Meu problema com esta resposta é que isso realmente não me ajuda, porque usamos uma CDN e, obviamente, não podemos controlar como a CDN define cabeçalhos programaticamente.
BT
6
Exemplo real (Nginx) na minha resposta abaixo - stackoverflow.com/a/12414239/6084
mjallday
71
Se caches ou CDNs forem uma preocupação, use o cabeçalho Vary para informar ao cache / CDN para manter respostas separadas para diferentes valores de cabeçalho de solicitação de Origem. Você incluiria um cabeçalho como "Vary: Origin" em sua resposta. O cache / CDN sabe que deve enviar uma resposta a uma solicitação com o cabeçalho "Origem: foo.example.com " e uma resposta diferente a uma solicitação com o cabeçalho "Origem: bar.example.com ".
Sean
10
@saturdayplace, se você tiver acesso ao cabeçalho Origin, estará no CORS.
Paul Draper
222

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");
}
Nikolay Ivanov
fonte
12
Por que não usar a abordagem sugerida em stackoverflow.com/a/1850482/11635 [e não enviou um curinga, apenas a origem solicitada]? Isso é apenas mais permissivo sem conseguir mais nada?
Ruben Bartelink
15
ter header('Access-Control-Allow-Origin: *')dito às vezes não pode usar curinga se o sinalizador de credenciais for verdadeiro - acontece quando header('Access-Control-Allow-Credentials: true')provavelmente. Portanto, é melhor permitir a $http_originprópria origem , se as condições forem atendidas.
Rakib
6
substituir a última linha com header("Access-Control-Allow-Origin: " . $http_origin);a fazê-lo funcionar
François Romain
2
Esse código parece falho, pois, se nenhum cabeçalho HTTP_ORIGIN for reconhecido, nenhum Access-Control-Allow-Origin será definido, deixando o script totalmente aberto.
Stephen R
9
@StephenR realmente "wide fechado" seria mais preciso, já que o objetivo deste é para abrir o script para outros domínios;)
Kaddath
113

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 .htaccess, funcionará com certeza.

Jay Dave
fonte
24
melhor solução para mim, mas adicionei suporte à porta (por exemplo, localhost: 3000 para desenvolvimento): SetEnvIf Origin "^ http (s)?: // (. + \.)? (localhost | stackoverflow.com | example1.com) ( : [0-9] +)? $ "Origin_is = $ 0
vszurma 04/11/2013
2
Das várias respostas ao redor do stackoverflow, essa foi a que funcionou.
Meetai.com 3/03/15
Eu precisava para adicionar Header set Access-Control-Allow-Credentials truepara que isso funcione como resposta 's @George
99 problemas - Sintaxe não é um
Isso funciona com certeza quando eu uso o Origin. Mas, em alguns casos, o Origin não está disponível em algumas solicitações e também é específico do navegador. Então, eu decidi usar em Referervez de Origin. Usando Refererobras, mas o problema é que ele define o URL completo de volta para Access-Control-Allow-OriginEu quero cortar o nome de domínio Referere atribuí-lo Access-Control-Allow-Origin. Algo como o resultado disso - echo http://example.com/index.php/ab/cd | cut -d'/' -f1,2,3no comando bash. É possível fazer o mesmo no arquivo conf (apache)? Qualquer ideia?
3AK
1
Isso não funciona para mim. Sempre com um erro de código 500 quando adiciono as 2 linhas. Na verdade, usando PHP 5.6.15
BoCyrill 3/16/16
91

Eu tive o mesmo problema com fontes woff, vários subdomínios tinham que ter acesso. Para permitir subdomínios, adicionei algo assim ao meu 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>

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

Staugaard
fonte
4
Fiz o truque. Apenas certifique-se de adaptar a expressão regular corretamente. Eu precisava adicionar um ponto de interrogação para permitir o próprio domínio, por exemplo, (.*\.?example\.org)para example.come sub.example.com.
trkoch
3
Alguma idéia de como adaptar isso para o IIS 7?
Mark
Isso não está derrotando o objetivo? O que impediria um usuário mal-intencionado de falsificar o valor do cabeçalho Origin?
Joseph Joseph
1
@ GrégoryJoseph Access-Control-Allow-Origin não se trata de ocultar recursos de alguém que possa solicitá-lo. Trata-se de impedir que um site malicioso faça com que os usuários finais liguem para o site. No caso de arquivos de fontes, isso só pode efetivamente limitar a vinculação direta de fontes, por que elas (mozilla / firefox) não fizeram o mesmo com outros recursos (js, css, etc) estão além de mim.
precisa saber é o seguinte
@ Trkoch, há um erro no seu regex, ele também permitirá subexample.com. Você deve alterá-lo para:((.*\.)?example\.org)
bluesmoon
65

A seguir, mostramos como repetir o cabeçalho Origin se ele corresponder ao seu domínio com o Nginx. Isso é útil se você deseja exibir vários subdomínios de fonte:

location /fonts {
    # this will echo back the origin header
    if ($http_origin ~ "example.org$") {
        add_header "Access-Control-Allow-Origin" $http_origin;
    }
}
mjallday
fonte
Não consigo entender como isso é diferente de: add_header Access-Control-Allow-Origin *; Gostaria de explicar?
Anoyz
isso retornará um cabeçalho que autoriza o navegador a enviar apenas solicitações do domínio especificado. se eu adivinhasse, diria que o navegador pode autorizar o conteúdo de outro domínio carregado nessa página para acessar o servidor.
mjallday
7
@Anoyz, por um lado, pode haver segurança aprimorada onde "Allow *" não é permitido, mas um nome de host especificado e correspondente para o cabeçalho de permissão funciona. Um exemplo aqui, se você deseja enviar informações de autorização entre domínios, não pode usar "Permitir *"
TCC
3
O .exemplo example.org é interpretado como qualquer valor, pois é uma expressão regular? Nesse caso, isso permitiria por engano um TLD de organização de exemplo personalizado?
stuckj
1
A regex correto deve ser "^example\.org$"porque você precisa ter certeza de que um hacker não pode deslizar através de seu regex com subdomainexample.org(o uso ^) ou example.orgevil(uso $) ou examplezorg(escape \.)
zeg
27

Aqui está o que eu fiz para um aplicativo PHP que está sendo solicitado 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_originvalor como próprio do Access-Control-Allow-Origincabeçalho em vez de retornar um *curinga.

Rakib
fonte
20

Você deve estar ciente de uma desvantagem: assim que você envia arquivos para uma CDN (ou qualquer outro servidor que não permita scripts) ou se seus arquivos são armazenados em cache em um proxy, alterando a resposta com base em 'Origem' cabeçalho da solicitação não funcionará.

Marca
fonte
4
Você poderia elaborar isso ou nos indicar algum lugar onde possamos procurar mais informações? Estou procurando fazer exatamente isso com o Limelight, e espero que você esteja errado. Um de nossos técnicos disse que, enquanto o servidor de sementes da CDN enviar o cabeçalho, a própria CDN o enviará. Ainda não foi testado
BT
12
Se caches ou CDNs forem uma preocupação, use o cabeçalho Vary para informar ao cache / CDN para manter respostas separadas para diferentes valores de cabeçalho de solicitação de Origem. Você incluiria um cabeçalho como "Vary: Origin" em sua resposta. O cache / CDN sabe que deve enviar uma resposta a uma solicitação com o cabeçalho "Origem: foo.example.com " e uma resposta diferente a uma solicitação com o cabeçalho "Origem: bar.example.com ".
Sean
Vary: Origin não é suportado pela Akamai , uma das maiores CDNs do mercado ... Mais detalhes disponíveis aqui também #
Brad Parks
20

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

<IfModule mod_headers.c>
    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
</IfModule>
George
fonte
4
Este trecho funciona perfeitamente para mim. Mas eu não entendo o que faz: D
Karl Adler
2
Isso funcionou para mim, embora eu tive que adicionar um '^' ie ... SetEnvIf Origem "^ http (s): // (www \.)?
gypsyDev
Faz praticamente o mesmo que stackoverflow.com/a/14034228/209139 . É que a sintaxe .htaccess é muito mais difícil de ler que o PHP. Header set Vary Originseria uma boa adição a esta resposta.
TRiG
1
Muito obrigado pela sua ajuda
fresco Perfeccionista
2
Eu tive que mudar AccessControlAllowOrigin=$0$1para AccessControlAllowOrigin=$0. Caso contrário, não funcionaria para origens HTTPS. http://example.comsaiu corretamente, mas https://example.comsaiu como https://example.coms, com um extra sno final.
TRiG 12/10
17

Para usuários do Nginx, permita o CORS para vários domínios. Gosto do exemplo do @ marshall, embora suas respostas correspondam apenas a um domínio. Para corresponder a uma lista de domínio e subdomínio, este regex facilita o trabalho com fontes:

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 fará eco apenas aos cabeçalhos "Controle de acesso-Permitir origem" que correspondam à lista de domínios fornecida.

Adriano Rosa
fonte
Pense que você precisa bloquear esse regex no final com \ z porque, caso contrário, domain3.com.badhacker.com teria acesso permitido.
Dft
@dft Definimos $ no final, o que faz isso
Adriano Rosa
Desculpe eu quis dizer no exemplo da essência, o post real por @AdrianoRosa faz a mesma coisa como \ z
DFT
16

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

Paco Zarate
fonte
13

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

Estou usando o Jersey REST 1.x

Configure o web.xml para conhecer o Jersey REST e o 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>

Aqui está o código para 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;
}

}
duvo
fonte
O link acima é expirado, você pode adicionar um novo, ou resposta atualização com mais detalhes, Graças
Rajkumar Samala
Eu adicionei mais detalhes, espero que isso ajude
duvo
12

Como mencionado acima, Access-Control-Allow-Origindeve ser único e Varydeve ser definido como Originse você estiver atrás de uma CDN (rede de entrega de conteúdo).

Parte relevante da minha configuração do 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';
}
hernvnc
fonte
tem set $corsalgum tipo de significado oculto, ou é apenas específico para o seu conifg? parece que ele pode ser omitido juntamente com a segundaif
mikezter
Isso mesmo, pode ser omitido se essa for a única condição que você testa para definir os cabeçalhos, eu tive vários na minha configuração.
Hernvnc 03/10/19
9

Talvez eu esteja errado, mas, tanto quanto eu posso ver, Access-Control-Allow-Origintem um "origin-list"parâmetro as.

Por definição, um 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

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

drAlberT
fonte
2
Essa parece ser uma interpretação correta das especificações; Dito isto, a especificação não parece ser totalmente suportada pelos navegadores atuais (por exemplo, eu apenas testei isso no Firefox 17.0 e confirmei que não funcionará).
Rick Riensche 3/12/12
7
A seção de especificação do CORS5.1 Access-Control-Allow-Origin Response Header afirma que a lista de origem é restrita: em vez de permitir uma lista de origens separada por espaço, é uma única origem ou a cadeia "nula".
Maxpolk
2
Como mencionei em um comentário na minha própria resposta, isso faz parte de uma observação dos implementadores, não um requisito da RFC 2119. A resposta 'correta' é absolutamente usar valores delimitados por espaço. O problema é simplesmente que as implementações estão incompletas e, portanto, a resposta 'correta' não funciona necessariamente. Deveria, mas não. No entanto, no futuro, à medida que as implementações melhorarem, isso poderá mudar.
Bob Aman
8

Para aplicativos ExpressJS, você pode usar:

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();
});
eyecatchUp
fonte
isso permitirá que todas as outras chamadas sejam feitas na próxima chamada ...
Ievgen Naida
@IevgenNaida So? Qual é o problema?
EyecatchUp
7

Eu lutei para configurá-lo para um domínio executando HTTPS, então imaginei que compartilharia a solução. Eu usei a seguinte diretiva no meu arquivo 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>

Mude example.compara o seu nome de domínio. Adicione isso dentro <VirtualHost x.x.x.x:xx>do seu arquivo httpd.conf . Observe que se o seu VirtualHosttiver um sufixo de porta (por exemplo :80), essa diretiva não se aplicará ao HTTPS, portanto você também precisará acessar / etc / apache2 / sites-available / default-ssl e adicionar a mesma diretiva nesse arquivo, dentro da <VirtualHost _default_:443>seção.

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

a2enmod headers
sudo service apache2 reload
Alex W
fonte
Eu gosto dessa opção e a combinei / modifiquei com a implementação que o @George possui. Às vezes, os servidores não têm o a2enmod disponível; portanto, tudo que você precisa fazer é verificar o seu httpd.conf principal para ver se a linha: LoadModule headers_module modules / mod_headers.so não é comentada.
Mike Kormendy
Como minha origem tinha um número de porta, modifiquei a expressão regular para incluir: ^http(s)?://(.+\.)?example\.com(:\d+)?$
indiv
5

Se você estiver tendo problemas com as fontes, use:

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

Uma abordagem mais flexível é usar as expressões do Apache 2.4. Você pode comparar com domínios, caminhos e praticamente todas as outras variáveis ​​de solicitação. Embora a resposta enviada seja sempre *, os únicos solicitantes que a recebem são os que atendem aos requisitos de qualquer maneira. O uso do Origincabeçalho de solicitação (ou qualquer outro) na expressão faz com que o Apache os mescle automaticamente no Varycabeçalho de resposta, para que a resposta não seja reutilizada para uma origem diferente.

<IfModule mod_headers.c>
    <If "%{HTTP:Host} =~ /\\bcdndomain\\.example$/i && %{HTTP:Origin} =~ /\\bmaindomain\\.example$/i">
        Header set Access-Control-Allow-Origin "*"
    </If>
</IfModule>
Walf
fonte
2
Eu vim aqui porque alguns navegadores não aceitam *credenciais como Login. Portanto, será melhor se você passar o nome do host correspondente em vez de *.
KeitelDOG 18/01/19
@KeitelDOG, como capturar dinamicamente a origem correta e enviá-la de volta quando houver várias origens, em vez de repetir o código para cada domínio? Parece que ele poderia ser possível com expressões mas os docs não são claras para mim.
Walf
Na verdade, meu verdadeiro problema foi porque o laravel não retornou o Access-Control-Allow-Origincabeçalho para a OPTIONSsolicitação de comprovação que verifica se há cabeçalhos para ver se o servidor permite essa origem. Eu consertei isso. Então *não era o verdadeiro problema para mim. Porém, alguns navegadores ainda não aceitam *credenciais; portanto, quando um aplicativo Web envia uma solicitação de origem cruzada, é necessário especificar o HTTP_ORIGINcabeçalho que você pode acessar dinamicamente com a variável Originin .htaccessApache ou $_SERVER['HTTP_ORIGIN'];PHP. De qualquer forma a sua solução é bom porque permite que todas as origens, mas menos segura
KeitelDOG
Mas duas coisas a lembrar é que 1) O fornecimento *permite tudo. 2) HOST é diferente de ORIGEM. HOST é o 'TARGET HOST' real que é passado para o cabeçalho da solicitação. Mas ORIGIN é o INITIAL HOSTque envia a solicitação para o TARGET HOST. Portanto, no seu código, ORIGIN HOSTé ignorado e nunca usado. Veja as respostas acima e você verá como eles usam ORIGINvalores para adicioná-los Access-Control-Allow-Origin.
KeitelDOG 22/01/19
@KeitelDOG *Não permite a todos, porque o uso do Origincabeçalho de solicitação na expressão faz com que o Apache o mescle automaticamente no Varycabeçalho de resposta, a menos que alguém o utilize req_novary('Origin')(provavelmente indesejável). Os navegadores sabem que podem obter uma resposta diferente para uma diferente Origine se o valor enviado não passar no teste de alguém, o Access-Control-Allow-Origincabeçalho nunca será definido.
Walf
3

Código 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');
Liakos
fonte
2

HTTP_ORIGIN não é usado por todos os navegadores. Quão seguro é HTTP_ORIGIN? Para mim, aparece vazio em FF.
Eu tenho os sites que permitem o acesso ao meu site enviando um ID do site, depois verifico meu banco de dados para o registro com esse ID e obtenho o valor da coluna SITE_URL (www.yoursite.com).

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

Mesmo se você enviar um ID de site válido, a solicitação precisará ser do domínio listado no meu banco de dados associado a esse ID de site.

mathius1
fonte
2

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

<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>
Mike Kormendy
fonte
2

Para facilitar o acesso a vários domínios para um serviço ASMX, criei esta função 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 manuseio do OPTIONSverbo CORS também.

Derek Wade
fonte
2

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);
}
blak3r
fonte
2

Para uma cópia / colar razoavelmente fácil para aplicativos .NET, escrevi isso para ativar o CORS de dentro de um global.asaxarquivo. Este código segue o conselho dado na resposta atualmente aceita, refletindo a origem na resposta. Isso efetivamente atinge '*' sem usá-lo.

O motivo disso é que ele habilita vários outros recursos 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" , "*");
    }
}
Controle de qualidade coletivo
fonte
1

E mais uma resposta no Django. Para que uma única visualização permita o CORS de vários domínios, eis 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
Silvain
fonte
1

Gateway AWS Lambda / API

Para obter informações sobre como configurar várias origens no AWS Lambda sem servidor e no API Gateway - embora uma solução bastante grande para algo que você ache que deva ser bastante simples - veja aqui:

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


No momento, não é possível configurar várias origens no API Gateway, consulte aqui: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html ), mas a recomendação (em a resposta acima) é:

  • inspecionar o cabeçalho de origem enviado pelo navegador
  • compará-lo com uma lista branca de origens
  • se corresponder, retorne a Origem de entrada como o cabeçalho Access-Control-Allow-Origin; caso contrário, retorne um espaço reservado (origem padrão).

A solução simples está obviamente habilitando ALL (*) assim:

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([{

Mas pode ser melhor fazer isso no lado do API Gateway (consulte o segundo link acima).

timhc22
fonte
2
Access-Control-Allow-Credentials: truenão é permitido com curinga Access-Control-Allow-Origin: *. Defina um específico <origin>.
Tom
@ Tom, sim, não sei por que isso estava lá, não me lembro, mas talvez eu o tenha copiado dos padrões adicionados à AWS? Obrigado por apontar isso embora.
timhc22 20/04
0

A resposta de suporte do Google na veiculação de anúncios por SSL e a gramática na própria RFC parece indicar que é possível delimitar espaço os URLs. Não tenho certeza de quão bem isso é suportado em diferentes navegadores.

Bob Aman
fonte
links 'veiculação de anúncios por ssl' para a especificação w3.org/TR/cors/#access-control-allow-origin-response-header, que acrescenta uma observação: "Na prática, a produção da lista de origem ou nula é mais restrita . ao invés de permitir uma lista separada por espaços de origens, é uma única origem ou a cadeia "nulo".
spazm
Embora seja importante observar esse detalhe, quando uma especificação diz "Na prática", isso não significa que só é válido fazê-lo dessa maneira. Isso significa que, se você fizer dessa maneira, poderá ter problemas porque a maioria dos implementadores implementa a especificação incorreta ou incompletamente. A especificação permite uma lista de origens separadas por espaço, que você pode ver aqui no EBNF em origin-list: tools.ietf.org/html/rfc6454#section-7.1
Bob Aman
0

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

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

Isso me ajudou a usar esse código depois de tentar muitas .htaccesssoluções puras e este parecia 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"

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

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

AlexioVay
fonte
0

A resposta abaixo é específica para C #, mas o conceito deve ser aplicável a todas as plataformas diferentes.

Para permitir solicitações de origem cruzada de uma API da web, é necessário permitir solicitações de opção ao seu aplicativo e adicionar anotação abaixo no nível do controlador.

[EnableCors (UrlString, Header, Method)] Agora, as origens podem ser passadas apenas como string. Portanto, se você deseja passar mais de um URL na solicitação, passe-o como um valor separado por vírgula.

UrlString = " https: //a.hello.com,https: //b.hello.com "

sakshi agrawal
fonte
0

Somente uma única origem pode ser especificada para o cabeçalho Access-Control-Allow-Origin. Mas você pode definir a origem da sua resposta de acordo com a solicitação. Também não se esqueça de definir o cabeçalho Vary. No PHP, eu faria o seguinte:

    /**
     * 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
  }
Simon
fonte
-2

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

    }
sudhAnsu63
fonte