Acceso-Control-Permitir-Origen ¿Dominios de origen múltiple?

1049

¿Hay alguna manera de permitir múltiples dominios cruzados usando el Access-Control-Allow-Originencabezado?

Soy consciente de esto *, pero está demasiado abierto. Realmente quiero permitir solo un par de dominios.

Como ejemplo, algo como esto:

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

He probado el código anterior pero no parece funcionar en Firefox.

¿Es posible especificar múltiples dominios o estoy atascado con solo uno?

Thomas J Bradley
fuente
3
Usando el Firefox más reciente, ni los dominios separados por comas ni los espacios separados por espacios funcionaron. Hacer coincidir una lista de dominios y poner un solo host en los encabezados es aún mejor seguridad y funciona correctamente.
Daniel W.
1
Si estás luchando con esto para HTTPS, encontré una solución .
Alex W
77
nota importante : permitir solo crear dominios en elAccess-Control-Allow-Originencabezado no significa que otros dominios no puedan activar un método en este punto final (por ejemplo, método REST API). Simplemente significa que los orígenes no permitidos no pueden usar el resultado en javascript (el navegador lo asegura). Para restringir el acceso a un punto final para dominios específicos, utilice un filtro de solicitud del lado del servidor que, por ejemplo, devuelva HTTP 401 para dominios no permitidos.
klues
1
Siempre debe agregar un Vary: Originencabezado cuando desee utilizar varias URL, consulte: fetch.spec.whatwg.org/#cors-protocol-and-http-caches
Nulo

Respuestas:

861

Parece que la forma recomendada de hacerlo es hacer que su servidor lea el encabezado Origin del cliente, compare eso con la lista de dominios que le gustaría permitir, y si coincide, repita el valor del Originencabezado de nuevo al cliente como el Access-Control-Allow-Originencabezado en la respuesta.

Con .htaccessusted puede hacerlo así:

# ----------------------------------------------------------------------
# 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
fuente
41
Esto coincide con lo que sugiere el W3C: w3.org/TR/cors/#access-control-allow-origin-response-hea
Simon B.
153
Mi problema con esta respuesta es que realmente no me ayuda, porque usamos un CDN, y obviamente no podemos controlar cómo el CDN establece los encabezados mediante programación.
BT
66
Ejemplo real (Nginx) en mi respuesta a continuación - stackoverflow.com/a/12414239/6084
mjallday
71
Si las memorias caché o CDN son motivo de preocupación, use el encabezado Vary para indicar a la memoria caché / CDN que mantenga respuestas separadas para diferentes valores de encabezado de solicitud de origen. Debería incluir un encabezado como "Variar: origen" en su respuesta. El caché / CDN sabe que debe enviar una respuesta a una solicitud con el encabezado "Origen: foo.example.com ", y una respuesta diferente a una solicitud con el encabezado "Origen: bar.example.com ".
Sean
10
@saturdayplace, si tiene acceso al encabezado Origin, ya pasó CORS.
Paul Draper
222

Otra solución que estoy usando en 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
fuente
12
¿Por qué no utilizar el enfoque sugerido en stackoverflow.com/a/1850482/11635 [y no envió un comodín, solo el origen solicitado]? ¿Esto es más permisivo sin lograr nada más?
Ruben Bartelink
15
tener a header('Access-Control-Allow-Origin: *')veces dice que no se puede usar comodín si el indicador de credenciales es verdadero, sucede cuando header('Access-Control-Allow-Credentials: true')probablemente. Por lo tanto, es mejor Permitir-Origen en $http_originsí mismo si se cumplen las condiciones
Rakib
66
reemplazar la última línea header("Access-Control-Allow-Origin: " . $http_origin);para que funcione
François Romain
2
Este código parece defectuoso, ya que si no se reconoce el encabezado HTTP_ORIGIN, no se establece Access-Control-Allow-Origin en absoluto, dejando el script completamente abierto.
Stephen R
99
@StephenR en realidad "completamente cerrado" sería más preciso, ya que el propósito de esto es abrir el script a otros dominios;)
Kaddath
113

Esto funcionó para mí:

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

Cuando se coloca .htaccess, funcionará seguro.

Jay Dave
fuente
24
la mejor solución para mí, pero agregué soporte de puerto (por ejemplo, localhost: 3000 para desarrollo): SetEnvIf Origin "^ http (s)?: // (. + \.)? (localhost | stackoverflow.com | example1.com) ( : [0-9] +)? $ "Origin_is = $ 0
vszurma
2
De las varias respuestas en torno a stackoverflow, esta fue la que funcionó.
Meetai.com
Necesitaba agregar Header set Access-Control-Allow-Credentials truepara que esto funcionara como la respuesta de @George
99 Problemas - La sintaxis no es una
Esto funciona seguro cuando uso Origin. Pero en algunos casos, Origin no está disponible en algunas solicitudes y también es específico del navegador. Entonces, decidí usar en Refererlugar de Origin. Usando Referertrabajos pero el problema es que restablece la URL completa a Access-Control-Allow-OriginQuiero cortar el nombre de dominio Referery asignarlo Access-Control-Allow-Origin. Algo así como el resultado de esto - echo http://example.com/index.php/ab/cd | cut -d'/' -f1,2,3en el comando bash. ¿Es posible hacer lo mismo en el archivo de configuración (apache)? ¿Alguna idea?
3AK
1
Esto no funciona para mi. Siempre tengo un error de código 500 cuando agrego las 2 líneas. Realmente usando PHP 5.6.15
BoCyrill
91

Tuve el mismo problema con woff-fonts, varios subdominios tenían que tener acceso. Para permitir subdominios, agregué algo como esto a mi 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 múltiples dominios, simplemente puede cambiar la expresión regular en SetEnvIf.

Staugaard
fuente
44
Hizo el truco. Solo asegúrese de adaptar la expresión regular correctamente. Necesitaba agregar un signo de interrogación para permitir el dominio en sí, por ejemplo, (.*\.?example\.org)para example.comy sub.example.com.
trkoch
3
¿Alguna idea sobre cómo adaptar esto para IIS 7?
Mark
¿Pero eso no es derrotar el propósito? ¿Qué evitaría que un usuario malintencionado falsifique el valor del encabezado Origin?
Grégory Joseph
1
@ GrégoryJoseph Access-Control-Allow-Origin no se trata de ocultar recursos de alguien que pueda solicitarlo. Se trata de evitar que un sitio malicioso tenga usuarios finales llamando a su sitio. En el caso de los archivos de fuentes, esto solo puede limitar efectivamente el enlace activo de las fuentes, por qué ellos (mozilla / firefox) no hicieron lo mismo para otros recursos (js, css, etc.) está más allá de mi alcance.
Rastreador1
@trkoch, hay un error en tu expresión regular, también lo permitirá subexample.com. Debe cambiarlo a:((.*\.)?example\.org)
bluesmoon
65

Aquí le mostramos cómo hacer eco del encabezado Origin si coincide con su dominio con Nginx, esto es útil si desea servir una fuente en varios subdominios:

location /fonts {
    # this will echo back the origin header
    if ($http_origin ~ "example.org$") {
        add_header "Access-Control-Allow-Origin" $http_origin;
    }
}
mjallday
fuente
No puedo entender cómo es esto diferente de: add_header Access-Control-Allow-Origin *; ¿Le importaria explicar?
Anoyz
esto devolverá un encabezado que autoriza al navegador a enviar solo solicitudes desde el dominio especificado. si supuse que diría que el navegador podría autorizar el contenido de otro dominio cargado en esa página para acceder al servidor de otra manera.
mjallday
77
@Anoyz, por un lado, puede haber una seguridad mejorada donde "Permitir *" no está permitido, pero funciona un nombre de host especificado y coincidente para el encabezado de permiso. Un ejemplo aquí, si desea enviar información de autorización entre dominios, no puede usar "Permitir *"
TCC
3
¿Se .interpreta in example.org como cualquier valor ya que esta es una expresión regular? En ese caso, ¿permitiría esto por error un TLD de ejemplo-organización personalizado?
stuckj
1
Una expresión regular correcta debería deberse a "^example\.org$"que debe asegurarse de que un hacker no pueda deslizarse a través de su expresión regular con subdomainexample.org(use ^) o example.orgevil(use $) o examplezorg(escape \.)
zeg
27

Esto es lo que hice para una aplicación PHP que AJAX solicita

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

Si mi servidor permite el origen de la solicitud, devuélvala $http_origincomo valor del Access-Control-Allow-Originencabezado en lugar de devolver un *comodín.

Rakib
fuente
20

Hay una desventaja que debe tener en cuenta: tan pronto como externalice los archivos a un CDN (o cualquier otro servidor que no permita secuencias de comandos) o si sus archivos se almacenan en caché en un proxy, alterando la respuesta basada en 'Origin' el encabezado de solicitud no funcionará.

marca
fuente
44
¿Podría dar más detalles sobre esto o indicarnos un lugar donde podamos buscar más información? Estoy buscando hacer eso con Limelight, y espero que te equivoques. Uno de nuestros técnicos de operaciones dijo que mientras nuestro servidor semilla CDN envíe el encabezado, la propia CDN lo enviará. Aún no lo he probado
BT
12
Si las memorias caché o las CDN son motivo de preocupación, use el encabezado Vary para indicarle a la memoria caché / CDN que mantenga respuestas separadas para diferentes valores de encabezado de solicitud de origen. Debería incluir un encabezado como "Variar: origen" en su respuesta. El caché / CDN sabe que debe enviar una respuesta a una solicitud con el encabezado "Origen: foo.example.com ", y una respuesta diferente a una solicitud con el encabezado "Origen: bar.example.com ".
Sean
Vary: Origin no es compatible con Akamai , uno de los mayores CDN que existen ... Más detalles disponibles aquí también
Brad Parks el
20

Para dominios múltiples, en su .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>
Jorge
fuente
44
Este fragmento funciona perfectamente para mí. Pero no entiendo lo que hace: D
Karl Adler
2
esto funcionó para mí, aunque tuve que agregar un '^' es decir ... SetEnvIf Origin "^ http (s)?: // (www \.)?
gypsyDev
Hace casi lo mismo que stackoverflow.com/a/14034228/209139 . Es solo que la sintaxis .htaccess es mucho más difícil de leer que PHP. Header set Vary Originsería una buena adición a esta respuesta.
TRiG
1
Muchas gracias por su ayuda
Cool Perfectionist
2
Tuve que cambiar AccessControlAllowOrigin=$0$1a AccessControlAllowOrigin=$0. De lo contrario, no funcionó para los orígenes HTTPS. http://example.comsalió correctamente, pero https://example.comsalió como https://example.coms, con un extra sen el final.
TRiG
17

Para usuarios de Nginx permitir CORS para múltiples dominios. Me gusta el ejemplo de @ marshall, aunque sus respuestas solo coinciden con un dominio. Para hacer coincidir una lista de dominio y subdominio, esta expresión regular facilita el trabajo con fuentes:

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

Esto solo hará eco de los encabezados "Access-Control-Allow-Origin" que coinciden con la lista de dominios dada.

Adriano Rosa
fuente
Cree que necesita bloquear esa expresión regular al final con \ z porque de lo contrario se permitiría el acceso a domain3.com.badhacker.com.
dft
@dft Definimos $ al final que hace eso
Adriano Rosa
Lo siento, quise decir en el ejemplo esencial, la publicación real de @AdrianoRosa hace lo mismo que \ z
dft
13

Aquí hay una solución para la aplicación web Java, basada en la respuesta de yesthatguy.

Estoy usando Jersey REST 1.x

Configure web.xml para conocer Jersey REST y 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>

Aquí está el 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
fuente
El enlace anterior ha caducado, ¿puede agregar uno nuevo o actualizar la respuesta con más detalles? Gracias
RajKumar Samala
He agregado más detalles, espero que esto ayude
duvo
12

Como se mencionó anteriormente, Access-Control-Allow-Origindebe ser único y Varydebe establecerse Originsi está detrás de una CDN (Content Delivery Network).

Parte relevante de mi configuración de 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
fuente
tiene set $corsalgún tipo de significado oculto, o es solo específico para su conífera? parece que se puede omitir junto con el segundoif
mikezter
Así es, se puede omitir si esa es la única condición que prueba para configurar los encabezados, tenía múltiples en mi configuración.
hernvnc
9

Tal vez estoy equivocado, pero hasta donde puedo ver Access-Control-Allow-Origintiene un "origin-list"parámetro como.

Por definición, un origin-listes:

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

Y a partir de esto, sostengo que se admiten diferentes orígenes y deben estar separados por espacios .

drAlberT
fuente
2
Eso parece ser una interpretación correcta de la especificación; Dicho esto, la especificación no parece ser totalmente compatible con los navegadores actuales (por ejemplo, acabo de probar esto en Firefox 17.0 y confirmó que no funcionará).
Rick Riensche
77
La sección de especificación CORS5.1 Access-Control-Allow-Origin Response Header establece que la lista de origen está restringida: en lugar de permitir una lista de orígenes separados por espacios, es un origen único o la cadena "nulo".
maxpolk
2
Como mencioné en un comentario sobre mi propia respuesta, eso es parte de una nota de los implementadores, no un requisito de RFC 2119. La respuesta 'correcta' es absolutamente usar valores delimitados por espacios. El problema es simplemente que las implementaciones están incompletas y, por lo tanto, la respuesta 'correcta' no necesariamente funciona. Debería, pero no lo hace. Sin embargo, en el futuro, a medida que las implementaciones mejoren, esto puede cambiar.
Bob Aman
8

Para las aplicaciones ExpressJS puede 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
fuente
esto permitirá todas las demás llamadas por una llamada siguiente ...
Ievgen Naida
@IevgenNaida ¿Entonces? ¿Cual es el problema?
eyecatchUp
7

Me costó configurar esto para un dominio que ejecuta HTTPS, así que pensé que compartiría la solución. Usé la siguiente directiva en mi archivo 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>

Cambia example.coma tu nombre de dominio. Agregue esto dentro <VirtualHost x.x.x.x:xx>de su archivo httpd.conf . Tenga en cuenta que si VirtualHosttiene un sufijo de puerto (por ejemplo :80), esta directiva no se aplicará a HTTPS, por lo que también deberá ir a / etc / apache2 / sites-available / default-ssl y agregar la misma directiva en ese archivo, dentro de la <VirtualHost _default_:443>sección.

Una vez que se actualizan los archivos de configuración, deberá ejecutar los siguientes comandos en el terminal:

a2enmod headers
sudo service apache2 reload
Alex W
fuente
Me gusta esta opción y la combiné / modifiqué con la implementación que tiene @George. A veces los servidores no tienen a2enmod disponible, por lo que todo lo que tiene que hacer es verificar su httpd.conf principal para ver si la línea: LoadModule headers_module modules / mod_headers.so no está comentada.
Mike Kormendy
Mi origen tenía un número de puerto, por lo que modifiqué la expresión regular para incluir eso: ^http(s)?://(.+\.)?example\.com(:\d+)?$
indiv
5

Si tiene problemas con las fuentes, use:

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

Un enfoque más flexible es usar las expresiones de Apache 2.4. Puede hacer coincidir dominios, rutas y casi cualquier otra variable de solicitud. Aunque la respuesta enviada siempre es *, los únicos solicitantes que la reciben son los que cumplen los requisitos de todos modos. El uso del Originencabezado de solicitud (o cualquier otro) en la expresión hace que Apache lo combine automáticamente en el Varyencabezado de respuesta, por lo que esa respuesta no se reutilizará para un origen 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
fuente
2
Vine aquí porque algunos navegadores no aceptan *credenciales como Iniciar sesión. Por lo tanto, será mejor si pasa el nombre de host coincidente en lugar de *.
KeitelDOG
@KeitelDOG, ¿cómo se captura dinámicamente el origen correcto y se lo devuelve cuando hay múltiples orígenes, en lugar de repetir el código para cada dominio? Parece que podría ser posible con expresiones, pero los documentos no están claros para mí.
Walf
De hecho, mi problema real fue porque laravel no devolvió el Access-Control-Allow-Originencabezado de la OPTIONSsolicitud de verificación previa que verifica los encabezados para ver si el servidor permite este origen. Lo tengo arreglado. Así que *no fue el verdadero problema para mí. Pero, aún algunos navegadores no aceptan *credenciales, por lo que cuando una aplicación web envía una solicitud de origen cruzado, DEBEN especificar un HTTP_ORIGINencabezado al que pueda acceder dinámicamente con la variable Originen .htaccessApache o $_SERVER['HTTP_ORIGIN'];en PHP. De todos modos, su solución es buena, ya que permite todos los orígenes, pero menos segura
KeitelDOG el
Pero 2 cosas para recordar es que 1) Proporcionar lo *permite todo. 2) HOST es diferente de ORIGEN. HOST es el "HOST OBJETIVO" real que se pasa al encabezado de solicitud. Pero ORIGIN es el INITIAL HOSTque envía la solicitud al TARGET HOST. Por lo tanto, en su código, ORIGIN HOSTse ignora y nunca se usa. Vea las respuestas anteriores y verá cómo usan los ORIGINvalores para agregarlos Access-Control-Allow-Origin.
KeitelDOG
@KeitelDOG *No permite a todos porque usar el Originencabezado de solicitud en la expresión hace que Apache lo combine automáticamente en el Varyencabezado de respuesta, a menos que se use req_novary('Origin')(probablemente no deseable). Los navegadores saben que pueden obtener una respuesta diferente para una diferente Originy si el valor enviado no pasa la prueba, el Access-Control-Allow-Originencabezado nunca se establece.
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
fuente
2

HTTP_ORIGIN no es utilizado por todos los navegadores. ¿Qué tan seguro es HTTP_ORIGIN? Para mí viene vacío en FF.
Tengo los sitios a los que autorizo ​​el acceso a mi sitio y los envío a través de una ID de sitio, luego verifico mi base de datos para el registro con esa identificación y obtengo el valor de la columna SITE_URL (www.yoursite.com).

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

Incluso si envía un ID de sitio válido, la solicitud debe ser del dominio que figura en mi base de datos asociada con ese ID de sitio.

mathius1
fuente
2

Aquí hay una opción ampliada para Apache que incluye algunas de las definiciones de fuente más recientes y planificadas:

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

Para facilitar el acceso a múltiples dominios para un servicio ASMX, creé esta función en el archivo 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();
    }
}

Esto permite el manejo CORS del OPTIONSverbo también.

Derek Wade
fuente
2

Ejemplo de código PHP para subdominios coincidentes.

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

Para una copia / pegado bastante fácil para aplicaciones .NET, escribí esto para habilitar CORS desde un global.asax archivo. Este código sigue los consejos dados en la respuesta actualmente aceptada, reflejando cualquier origen devuelto en la solicitud en la respuesta. Esto efectivamente logra '*' sin usarlo.

La razón de esto es que habilita varias otras funciones de CORS , incluida la capacidad de enviar una AJAX XMLHttpRequest con el atributo 'withCredentials' establecido en 'verdadero'.

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" , "*");
    }
}
QA Collective
fuente
1

Y una respuesta más en Django. Para tener una vista única que permita CORS desde múltiples dominios, aquí está mi 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
fuente
1

AWS Lambda / API Gateway

Para obtener información sobre cómo configurar múltiples orígenes en AWS Lambda y API Gateway sin servidor, aunque una solución bastante grande para algo que uno sentiría debería ser bastante sencillo, consulte aquí:

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


Actualmente no es posible configurar múltiples orígenes en API Gateway, consulte aquí: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html ), pero la recomendación (en la respuesta anterior) es:

  • inspeccionar el encabezado de origen enviado por el navegador
  • compárelo con una lista blanca de orígenes
  • si coincide, devuelva el origen entrante como el encabezado Access-Control-Allow-Origin; de lo contrario, devuelva un marcador de posición (origen predeterminado).

Obviamente, la solución simple es habilitar ALL (*) así:

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

Pero podría ser mejor hacer esto en el lado de API Gateway (ver el segundo enlace más arriba).

timhc22
fuente
2
Access-Control-Allow-Credentials: trueno está permitido con comodines Access-Control-Allow-Origin: *. Establecer un específico en su <origin>lugar.
Tom
@Tom, sí, no estoy seguro de por qué eso estaba allí, no lo recuerdo, pero ¿podría haberlo copiado de los valores predeterminados que se agregaron en AWS? Gracias por señalar eso sin embargo.
timhc22
0

La respuesta de soporte de Google sobre la publicación de anuncios a través de SSL y la gramática en el RFC en sí parece indicar que puede delimitar el espacio de las URL. No estoy seguro de qué tan bien soportado está en diferentes navegadores.

Bob Aman
fuente
enlaces de 'publicación de anuncios a través de ssl' a la especificación w3.org/TR/cors/#access-control-allow-origin-response-header que agrega una nota: "En la práctica, la producción de lista de origen o nula está más restringida . En lugar de permitir una lista de orígenes separados por espacios, es un origen único o la cadena "nulo".
spazm
Si bien es importante tener en cuenta ese detalle, cuando una especificación dice "En la práctica", no significa que solo sea válido hacerlo de esa manera. Significa que si lo hace de esa manera, puede tener problemas porque la mayoría de los implementadores implementan la especificación de manera incorrecta o incompleta. La especificación permite una lista de orígenes separados por espacios, que puede ver aquí en el EBNF en origin-list: tools.ietf.org/html/rfc6454#section-7.1
Bob Aman
0

Si prueba tantos ejemplos de código como yo para que funcione con CORS, vale la pena mencionar que primero debe borrar su caché para probar si realmente funciona, similar a problemas como cuando las imágenes antiguas todavía están presentes, incluso si es eliminado en el servidor (porque todavía está guardado en su caché).

Por ejemplo CTRL + SHIFT + DEL en Google Chrome para eliminar su caché.

Esto me ayudó a usar este código después de probar muchas .htaccesssoluciones puras y esta parecía ser la única que funcionaba (al menos para mí):

    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>

También tenga en cuenta que está muy extendido que muchas soluciones dicen que tiene que escribir, Header set ...pero es así Header add .... Espero que esto ayude a alguien que tiene los mismos problemas durante algunas horas como yo.

AlexioVay
fuente
0

La siguiente respuesta es específica de C #, pero el concepto debería ser aplicable a todas las plataformas diferentes.

Para permitir solicitudes de origen cruzado desde una API web, debe permitir las solicitudes de opción a su aplicación y agregar la anotación a continuación en el nivel del controlador.

[EnableCors (UrlString, Header, Method)] Ahora los orígenes se pueden pasar solo como una cadena. Entonces, si desea pasar más de una URL en la solicitud, páselo como un valor separado por comas.

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

sakshi agrawal
fuente
0

Solo se puede especificar un origen único para el encabezado Access-Control-Allow-Origin. Pero puede establecer el origen en su respuesta de acuerdo con la solicitud. Además, no olvide configurar el encabezado Vary. En PHP haría lo siguiente:

    /**
     * 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
  }
Simón
fuente
-2

También podemos configurar esto en el archivo Global.asax para la aplicación 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
fuente