Sottodomini, porte e protocolli con caratteri jolly di Access-Control-Allow-Origin

Sto cercando di abilitare CORS per tutti i sottodomini, le porte e il protocollo.

Ad esempio, voglio essere in grado di eseguire una richiesta XHR da http://sub.mywebsite.com:8080/ a https://www.mywebsite.com/ *

In genere, vorrei abilitare la richiesta da origini corrispondenti (e limitate a):

//*.mywebsite.com:*/*

Basandomi sulla risposta di DaveRandom, mi sono anche divertito e ho trovato una soluzione Apache leggermente più semplice che produce lo stesso risultato ( Access-Control-Allow-Origin è impostato sul protocollo specifico corrente + dominio + porta dynamicmente) senza utilizzare alcuna regola di riscrittura:

 SetEnvIf Origin ^(https?://.+\.mywebsite\.com(?::\d{1,5})?)$ CORS_ALLOW_ORIGIN=$1 Header append Access-Control-Allow-Origin %{CORS_ALLOW_ORIGIN}e env=CORS_ALLOW_ORIGIN Header merge Vary "Origin" 

E questo è tutto.

Coloro che desiderano abilitare CORS sul dominio padre (ad esempio, mywebsite.com) oltre a tutti i relativi sottodomini possono semplicemente sostituire l’espressione regolare nella prima riga con questo:

^(https?://(?:.+\.)?mywebsite\.com(?::\d{1,5})?)$ .

Nota: per la conformità delle specifiche e il corretto comportamento di memorizzazione nella cache, aggiungere SEMPRE l’intestazione di risposta Vary: Origin per le risorse abilitate per CORS, anche per le richieste non CORS e quelle di origine non consentita (vedere esempio perché ).

Le specifiche CORS sono tutte o niente. Supporta solo * , null o il protocollo esatto + dominio + porta: http://www.w3.org/TR/cors/#access-control-allow-origin-response-header

Il tuo server dovrà convalidare l’intestazione di origine usando la regex, e quindi puoi echo il valore di origine nell’intestazione di risposta Access-Control-Allow-Origin.

EDIT : utilizzare la soluzione @ Noyo al posto di questa. È più semplice, più chiaro e probabilmente molto più performante sotto carico.

RISPOSTA ORIGINALE QUI SOLO PER SCOPI STORICI SOLO !!


Ho fatto un po ‘di gioco con questo problema e ho trovato questa soluzione .htaccess (o httpd.conf) riutilizzabile che funziona con Apache:

   # Define the root domain that is allowed SetEnvIf Origin .+ ACCESS_CONTROL_ROOT=yourdomain.com # Check that the Origin: matches the defined root domain and capture it in # an environment var if it does RewriteEngine On RewriteCond %{ENV:ACCESS_CONTROL_ROOT} !="" RewriteCond %{ENV:ACCESS_CONTROL_ORIGIN} ="" RewriteCond %{ENV:ACCESS_CONTROL_ROOT}&%{HTTP:Origin} ^([^&]+)&(https?://(?:.+?\.)?\1(?::\d{1,5})?)$ RewriteRule .* - [E=ACCESS_CONTROL_ORIGIN:%2] # Set the response header to the captured value if there was a match Header set Access-Control-Allow-Origin %{ACCESS_CONTROL_ORIGIN}e env=ACCESS_CONTROL_ORIGIN   

Basta impostare la variabile ACCESS_CONTROL_ROOT nella parte superiore del blocco sul tuo dominio di root e farà eco il valore di intestazione Origin: request al client nel valore Access-Control-Allow-Origin: response se corrisponde al tuo dominio.

Si noti inoltre che è ansible utilizzare sub.mydomain.com come ACCESS_CONTROL_ROOT e limiterà le origini a sub.mydomain.com e *.sub.mydomain.com (ovvero non deve essere la radice del dominio). Gli elementi che possono variare (protocollo, porta) possono essere controllati modificando la porzione di corrispondenza dell’URI della regex.

Sto rispondendo a questa domanda, perché la risposta accettata non può corrispondere al dominio principale e funziona solo per il dominio secondario. Inoltre, il raggruppamento delle espressioni regolari è un successo nelle prestazioni , che non è necessario.

Ad esempio: non invierà intestazioni CORS per http://mywebsite.com mentre lavora per http://somedomain.mywebsite.com/

 SetEnvIf Origin "http(s)?://(.+\.)?mywebsite\.com(:\d{1,5})?$" CORS=$0 Header set Access-Control-Allow-Origin "%{CORS}e" env=CORS Header merge Vary "Origin" 

Per abilitare per il tuo sito, devi semplicemente mettere il tuo sito al posto di “mywebsite.com” nella Configurazione di Apache sopra.

Per consentire più siti:

 SetEnvIf Origin "http(s)?://(.+\.)?(othersite\.com|mywebsite\.com)(:\d{1,5})?$" CORS=$0 

Test dopo la distribuzione:

La seguente risposta di arricciatura dovrebbe avere l’intestazione “Access-Control-Allow-Origin” dopo la modifica.

 curl -X GET -H "Origin: http://examplesite1.com" --verbose http://examplesite2.com/query 

Avevo bisogno di una soluzione solo PHP, quindi nel caso qualcuno ne avesse bisogno. Richiede una stringa di input consentita come “* .example.com” e restituisce il nome del server dell’intestazione della richiesta, se l’input corrisponde.

 function getCORSHeaderOrigin($allowed, $input) { if ($allowed == '*') { return '*'; } $allowed = preg_quote($allowed, '/'); if (($wildcardPos = strpos($allowed, '*')) !== false) { $allowed = str_replace('*', '(.*)', $allowed); } $regexp = '/^' . $allowed . '$/'; if (!preg_match($regexp, $input, $matches)) { return 'none'; } return $input; } 

E qui ci sono i casi di test per un fornitore di dati phpunit:

 //     array('Allow Subdomain', 'www.example.com', 'www.example.com', 'www.example.com'), array('Disallow wrong Subdomain', 'www.example.com', 'ws.example.com', 'none'), array('Allow All', '*', 'ws.example.com', '*'), array('Allow Subdomain Wildcard', '*.example.com', 'ws.example.com', 'ws.example.com'), array('Disallow Wrong Subdomain no Wildcard', '*.example.com', 'example.com', 'none'), array('Allow Double Subdomain for Wildcard', '*.example.com', 'abexample.com', 'abexample.com'), array('Don\'t fall for incorrect position', '*.example.com', 'a.example.com.evil.com', 'none'), array('Allow Subdomain in the middle', 'a.*.example.com', 'a.bc.example.com', 'a.bc.example.com'), array('Disallow wrong Subdomain', 'a.*.example.com', 'b.bc.example.com', 'none'), array('Correctly handle dots in allowed', 'example.com', 'exampleXcom', 'none'), 

Avevamo problemi simili con Font Awesome su un dominio statico “cookie-less” durante la lettura di caratteri dal “dominio dei cookie” (www.domain.tld) ​​e questo post era il nostro eroe. Vedi qui: Come posso risolvere il problema Webfont di “Missing Cross-Origin Resource Sharing (CORS) Header”?

Per i tipi copia / incolla-r (e per dare alcuni oggetti di scena) ho messo insieme questo da tutti i contributi e l’ho aggiunto all’inizio del file .htaccess della radice del sito:

SetEnvIf Origin "http(s)?://(.+\.)?(othersite\.com|mywebsite\.com)(:\d{1,5})?$" CORS=$0 Header set Access-Control-Allow-Origin "%{CORS}e" env=CORS Header merge Vary "Origin"

Super sicuro, super elegante. Ti piace: non devi aprire la larghezza di banda dei tuoi server ai ladri di risorse / ai tipi hot-link-er.

Puntelli per: @Noyo @DaveRandom @ pratap-koritala

(Ho provato a lasciare questo come commento alla risposta accettata, ma non posso ancora farlo)

Sembra che la risposta originale fosse per il pre Apache 2.4. Non ha funzionato per me. Ecco cosa dovevo cambiare per farlo funzionare in 2.4. Ciò funzionerà per qualsiasi sottodominio di yourcompany.com .

 SetEnvIf Host ^((?:.+\.)*yourcompany\.com?)$ CORS_ALLOW_ORIGIN=$1 Header append Access-Control-Allow-Origin %{REQUEST_SCHEME}e://%{CORS_ALLOW_ORIGIN}e env=CORS_ALLOW_ORIGIN Header merge Vary "Origin" 

Con una leggera modifica sulla risposta di Lars.

 < ?php function validateOrigin($allowed, $input) { if ($allowed == '*') { return '*'; } $allowed = preg_quote($allowed, '/'); if (($wildcardPos = strpos($allowed, '\*')) !== false) { $allowed = str_replace('\*', '(.*)', $allowed); } $regexp = '/^' . $allowed . '$/'; if (!preg_match($regexp, $input, $matches)) { return 'none'; } return $input; } // CORS Preflight if($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { header('Access-Control-Allow-Origin: '.validateOrigin('https://*.domain.com', $_SERVER['HTTP_ORIGIN'])); header('X-Response-Code: 204', true, 204); header('Access-Control-Allow-Methods: GET'); header('Access-Control-Allow-Headers: Content-Type'); } elseif($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['VARIABLEHERE']) ) { // CODE HERE if($info["http_code"] === 200){ // 200 OK header('Content-type: application/json; charset=utf-8'); // CORS headers header('Access-Control-Allow-Origin: '.validateOrigin('https://*.domain.com', $_SERVER['HTTP_ORIGIN'])); echo $response; } else { header('X-Service-Response-Code: '.$info["http_code"], true, $info["http_code"]); } } else { // 400 bad request. header('X-Response-Code: 400', true, 400); } exit;