Domanda

C'è un modo per consentire a più trasversali domini utilizzando l'intestazione Access-Control-Allow-Origin?

Sono consapevole del *, ma è troppo aperto. Ho molta voglia di permettere solo un paio di domini.

Per fare un esempio, qualcosa di simile a questo:

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

Ho provato il codice di cui sopra, ma non sembra funzionare in Firefox.

E 'possibile specificare più domini o sono io bloccato con un solo?

È stato utile?

Soluzione

Suona come il metodo consigliato per farlo è quello di avere il server leggere l'intestazione di origine da parte del cliente, si confronti con l'elenco dei domini che si desidera consentire, e se corrisponde, eco il valore dell'intestazione Origin indietro al client come l'intestazione Access-Control-Allow-Origin nella risposta.

Con .htaccess si può fare in questo modo:

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

Altri suggerimenti

Un'altra soluzione che sto utilizzando in 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");
}

Questo ha funzionato per me:

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

Una volta messo in .htaccess, funzionerà di sicuro.

Ho avuto lo stesso problema con WOFF-fonts, più sottodomini doveva avere accesso. Per consentire sottodomini ho aggiunto qualcosa di simile al mio 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>

Per più domini basta solo cambiare la regex in SetEnvIf.

Ecco come eco l'intestazione Origine indietro se corrisponde al tuo dominio con Nginx, questo è utile se si vuole servire un font più sottodomini:

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

Ecco quello che ho fatto per un'applicazione PHP che viene richiesto da 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 l'origine la richiesta è consentito dal mio server, riportare il $http_origin stessa come valore dell'intestazione Access-Control-Allow-Origin invece di restituire un jolly *.

Non è uno svantaggio si dovrebbe essere a conoscenza: non appena si file out-source a un CDN (o qualsiasi altro server che non permette di scripting) o se i file vengono memorizzati nella cache su un proxy, alterando la risposta basata su intestazione di richiesta 'Origin' non funziona.

Per più domini, in .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>

Per gli utenti Nginx per consentire CORS per più domini. Mi piace l'@ esempio di Marshall anche se le sue partite anwers un solo dominio. Per trovare una lista di dominio e sottodominio questo regex rendono la facilità di lavorare con i font:

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

Questo sarà solo eco intestazioni "Access-Control-Allow-Origin" che corrisponde con l'elenco dei domini data.

Per IIS 7.5+ con URL Rewrite Module 2.0 installato consulta questo SO rispondere

Ecco una soluzione per Java web app, basata la risposta da yesthatguy.

Sto usando Jersey REST 1.x

Configurare il web.xml di essere a conoscenza di Jersey REST e il 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>

Ecco il codice per 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;
}

}

Come accennato in precedenza, Access-Control-Allow-Origin dovrebbe essere unico e Vary dovrebbe essere impostato a Origin se sei dietro un CDN (Content Delivery Network).

parte rilevante della mia configurazione 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';
}

Forse mi sbaglio, ma per quanto posso vedere Access-Control-Allow-Origin ha un "origin-list" come parametro.

definizione un 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 da questo, io sostengo diverse origini sono ammesse e devono essere spazio separato .

ho faticato a impostare questa funzione per un dominio in esecuzione HTTPS, così ho pensato che avrei condiviso la soluzione. Ho usato la seguente direttiva nel mio httpd.conf file:

    <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.com al tuo nome di dominio. Aggiungere questo <VirtualHost x.x.x.x:xx> all'interno nel file di httpd.conf . Si noti che se il vostro VirtualHost ha un suffisso di porta (ad es :80) allora questa direttiva non si applicherà a HTTPS, quindi sarà necessario andare anche a / etc / apache2 / sites-available / default-ssl e aggiungere lo stesso direttiva in quel file, all'interno della sezione <VirtualHost _default_:443>.

Una volta che i file di configurazione vengono aggiornati, è necessario eseguire i seguenti comandi nel terminale:

a2enmod headers
sudo service apache2 reload

Se si hanno problemi con i font, utilizzo:

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

Per le applicazioni ExpressJS è possibile utilizzare:

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

HTTP_ORIGIN non viene utilizzato da tutti i browser. Quanto è sicuro HTTP_ORIGIN? Per me si tratta mani vuote in FF.
Ho i siti che mi consentono di accedere al mio sito inviare più di un ID sito, ho poi controllare il mio DB per il record con tale ID e ottenere il valore della colonna SITE_URL (www.yoursite.com).

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

Anche se l'invio nel corso di un ID sito valida la richiesta deve essere dal dominio elencato nel mio DB associato a quel sito ID.

Ecco un'opzione espansa per Apache che include alcune delle più recenti e definizioni di carattere previsti:

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

E una risposta più in Django. Per avere una visione unica consentire CORS da più domini, qui è il mio codice:

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

Per un abbastanza facile copia / incolla per le applicazioni .NET, ho scritto questo per consentire CORS all'interno di un file Global.asax. Questo codice segue il consiglio dato nella risposta attualmente accettato, che riflette tutto ciò che di nuovo viene dato origine nella richiesta nella risposta. Questo raggiunge in modo efficace '*' senza usarlo. La ragione di questo è che consente a più altre caratteristiche CORS, tra cui la possibilità di inviare un AJAX XMLHttpRequest con l'attributo 'withCredentials' impostata su '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" , "*");
    }
}

Per facilitare l'accesso a più domini per un servizio ASMX, ho creato questa funzione nel file 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();
    }
}

In questo modo per la movimentazione di OPTIONS verb anche CORS.

esempio di codice PHP per la corrispondenza sottodomini.

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

Un approccio più flessibile è quello di utilizzare le espressioni Apache 2.4 di. È possibile abbinare contro i domini, percorsi e quasi ogni altra variabile richiesta. Anche se la risposta viene * per tutti, gli unici richiedenti che ricevono che la risposta sono quelli che soddisfano i requisiti in ogni caso.

<IfModule mod_headers.c>
    <If "%{HTTP:Host} =~ /\\bcdndomain\\.example$/i && %{HTTP:Origin} =~ /\\bmaindomain\\.example$/i">
        Header set Access-Control-Allow-Origin "*"
    </If>
</IfModule>

Risposta supporto di Google su la pubblicazione degli annunci su SSL e la grammatica del RFC per sé sembrerebbe indicare che è possibile delimitare lo spazio gli URL. Non sicuro come ben supportato questo è in diversi browser.

Se si tenta tanti esempi di codice, come me, per farlo funzionare con CORS, vale la pena di menzionare che è necessario svuotare la cache prima di provare se funziona davvero, simile a questioni come quando vecchie immagini sono ancora presenti, anche se è cancellato sul server (perché è ancora salvato nella cache).

Ad esempio CTRL + MAIUSC + CANC in Google Chrome per cancellare la cache.

Questo mi ha aiutato utilizzando questo codice dopo aver provato molte soluzioni pura .htaccess e questo sembrava l'unico a lavorare (almeno per me):

    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>

Si noti inoltre che è ampiamente diffuso che molte soluzioni dire dovete digitare Header set ... ma è Header add .... Spero che questo aiuta qualcuno che ha gli stessi problemi per alcune ore oggi, come me.

Di seguito la risposta è specifico per C #, ma il concetto dovrebbe essere applicabile a tutte le diverse piattaforme.

Per consentire le richieste Croce origine da un'API Web, è necessario per consentire le richieste opzione per l'applicazione e Aggiungi al di sotto di annotazione a livello di controllo.

[EnableCors (urlString, Intestazione, Method)] Ora le origini possono essere passati solo una stringa s. Quindi, se si vuole passare più di un URL nella richiesta passa come valore separati da virgole.

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

Una sola origine può essere specificato per l'intestazione Access-Control-Allow-Origin. Ma è possibile impostare l'origine nella vostra risposta in base alla richiesta. Inoltre, non dimenticare di impostare l'intestazione Vary. In PHP vorrei fare quanto segue:

    /**
     * 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
  }

Possiamo anche impostare questo nel file Global.asax per l'applicazione Asp.net.

protected void Application_BeginRequest(object sender, EventArgs e)
    {

    // enable CORS
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "https://www.youtube.com");

    }

La risposta sembra essere quello di utilizzare l'intestazione più di una volta. Cioè, invece di inviare

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

inviare

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

In Apache, è possibile farlo in una sezione httpd.conf <VirtualHost> o il file .htaccess usando mod_headers e questa sintassi:

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"

Il trucco è quello di utilizzare add piuttosto che append come primo argomento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top