Question

Y at-il un moyen de permettre à plusieurs domaines croisés en utilisant l'en-tête de Access-Control-Allow-Origin?

Je suis au courant de la *, mais il est trop ouvert. Je veux vraiment laisser juste un couple de domaines.

À titre d'exemple, quelque chose comme ceci:

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

Je l'ai essayé le code ci-dessus, mais il ne semble pas fonctionner dans Firefox.

Est-il possible de spécifier plusieurs domaines ou suis-je coincé avec un seul?

Était-ce utile?

La solution

Sons comme la méthode recommandée pour le faire est d'avoir votre serveur lire l'en-tête d'origine du client, comparer à la liste des domaines que vous souhaitez autoriser, et si elle correspond, retour d'écho la valeur de l'en-tête de Origin au client comme l'en-tête Access-Control-Allow-Origin dans la réponse.

Avec .htaccess vous pouvez le faire comme ceci:

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

Autres conseils

Une autre solution que je utilise 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");
}

Cela a fonctionné pour moi:

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

Quand mis en .htaccess, il fonctionnera à coup sûr.

J'ai eu le même problème avec les polices WOFF-, plusieurs sous-domaines devaient avoir accès. Pour permettre à des sous-domaines j'ajouté quelque chose comme ça à mon 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>

Pour plusieurs domaines vous pourriez simplement changer l'expression rationnelle dans SetEnvIf.

Voici comment écho l'en-tête d'origine en arrière si elle correspond à votre domaine avec Nginx, ce qui est utile si vous voulez servir une police plusieurs sous-domaines:

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

Voici ce que je l'ai fait pour une application PHP qui est demandé par 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);
}

Si l'origine la demande est autorisée par mon serveur, le retour $http_origin lui-même comme valeur de l'en-tête de Access-Control-Allow-Origin au lieu de retourner un caractère générique *.

Il y a un inconvénient, vous devez être au courant: Dès que vous hors des fichiers source à un CDN (ou tout autre serveur qui ne permet pas les scripts) ou si vos fichiers sont mises en cache sur un proxy, une réponse basée sur la modification tête de requête « origine » ne fonctionnera pas.

Pour plusieurs domaines, dans votre .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>

Pour les utilisateurs Nginx pour permettre CORS pour plusieurs domaines. J'aime le @ exemple de marshall, bien que ses anwers correspond à un seul domaine. Pour correspondre à une liste de domaine et sous-domaine cette regex rendent la facilité à travailler avec des polices:

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

Cela n'echo "Access-Control-Allow-Origin" en-têtes qui correspond à la liste donnée des domaines.

Pour IIS 7.5+ avec l'URL Rewrite Module 2.0 installé s'il vous plaît voir cette réponse SO

Voici une solution pour application Web Java, base la réponse de yesthatguy.

J'utilise 1.x Jersey REST

Configurer le web.xml pour être au courant de Jersey reposiez, et le 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>

Voici le code pour 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;
}

}

Comme mentionné ci-dessus, Access-Control-Allow-Origin doit être unique et Vary doit être réglé sur Origin si vous êtes derrière un CDN (Content Delivery Network).

La partie pertinente de ma configuration 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';
}

Peut-être que je me trompe, mais pour autant que je peux voir Access-Control-Allow-Origin a un "origin-list" comme paramètre.

définition un origin-list est:

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

Et de cela, je soutiens origines différentes sont admises et doivent être séparés par des espaces .

J'eu du mal à mettre en place pour un domaine HTTPS en cours d'exécution, donc je pensais que je partagerais la solution. Je la directive suivante dans mon httpd.conf fichier:

    <FilesMatch "\.(ttf|otf|eot|woff)$">
            SetEnvIf Origin "^http(s)?://(.+\.)?example\.com$" AccessControlAllowOrigin=$0
            Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
    </FilesMatch>

Modifier example.com à votre nom de domaine. Ajouter ceci à l'intérieur <VirtualHost x.x.x.x:xx> dans votre httpd.conf fichier . Notez que si votre VirtualHost a un suffixe de port (par exemple :80), cette directive ne sera pas applicable à HTTPS, vous devrez donc aller aussi / etc / apache2 / sites disponibles / default-ssl et ajouter la même directive dans ce dossier, à l'intérieur de la section <VirtualHost _default_:443>.

Une fois que les fichiers de configuration sont mis à jour, vous devrez exécuter les commandes suivantes dans le terminal:

a2enmod headers
sudo service apache2 reload

Si vous rencontrez des problèmes avec les polices, utilisez:

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

Pour les applications express.js vous pouvez utiliser:

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 n'est pas utilisé par tous les navigateurs. Comment sécuriser HTTP_ORIGIN? Pour moi, il arrive vide à FF.
Je les sites que j'autoriser l'accès à mon site envoyer sur un ID de site, je puis vérifier mon DB pour l'enregistrement avec cet identifiant et obtenir la valeur de la colonne SITE_URL (www.yoursite.com).

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

Même si l'envoi sur un site d'identité valide la demande doit être du domaine indiqué dans mon DB associé à cet identifiant du site.

Voici une option élargie pour apache qui comprend certaines des dernières et des définitions de police prévues:

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

Et une réponse à Django. Pour avoir une vue unique permet CORS de multiples domaines, voici mon code:

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

Pour copier / coller assez facile pour les applications .NET, j'ai écrit ceci pour permettre CORS à partir d'un fichier global.asax. Ce code suit les conseils donnés dans la réponse actuellement acceptée, ce qui reflète tout retour est prévue dans la demande dans la réponse. Cela permet d'atteindre efficacement « * » sans l'utiliser. La raison de cela est qu'il permet à plusieurs autres fonctionnalités CORS, y compris la possibilité d'envoyer un AJAX XMLHttpRequest avec l'attribut 'withCredentials de la valeur « 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" , "*");
    }
}

Pour faciliter l'accès multiple de domaine pour un service ASMX, j'ai créé cette fonction dans le fichier 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();
    }
}

Cela permet CORS manipulation du verbe OPTIONS aussi.

exemple de code PHP pour les sous-domaines correspondant.

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

Une approche plus flexible est d'utiliser les expressions d'Apache 2.4. Vous pouvez faire correspondre contre les domaines, les chemins, et à peu près toutes les autres variables de la demande. Bien que la réponse est * pour tous, les seuls qui reçoivent cette réponse les demandeurs sont ceux qui répondent aux exigences de toute façon.

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

soutien de Google réponse sur diffuser des annonces sur SSL et grammaire dans la RFC elle-même semble indiquer que vous pouvez l'espace délimiter les URL. Je ne sais pas comment bien supporté cela est dans les différents navigateurs.

Si vous essayez tant d'exemples de code comme moi pour le faire fonctionner à l'aide CORS, il vaut la peine de mentionner que vous devez effacer votre cache premier à essayer si cela fonctionne réellement, similaire à des questions telles que quand les vieilles images sont encore présentes, même si elle est supprimé sur le serveur (car il est toujours enregistré dans le cache).

Par exemple CTRL + SHIFT + DEL dans Google Chrome pour supprimer votre cache.

Cela m'a aidé en utilisant ce code après avoir essayé de nombreuses solutions de .htaccess pure et cela semblait le seul à travailler (au moins pour moi):

    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>

Notez également qu'il est largement répandu que beaucoup de solutions que vous avez à taper Header set ... mais il est Header add .... Espérons que cela aide quelqu'un ayant les mêmes problèmes pour quelques heures maintenant comme moi.

Ci-dessous réponse est spécifique à C #, mais le concept devrait être applicable à toutes les différentes plates-formes.

Pour permettre à la Croix Origine Demandes d'un api web, vous devez autoriser les demandes d'options à votre application et ajoutez ci-dessous annotation au niveau du contrôleur.

[EnableCors (URLString, En-tête, méthode)] Maintenant, les origines peuvent être transmises que une chaîne de s. Donc, si vous voulez passer plus d'une URL dans la demande passe comme une virgule valeur seperated.

URLString = « https: //a.hello.com,https: //b.hello.com "

Seule une origine unique peut être spécifiée pour l'en-tête Access-Control-Allow-Origin. Mais vous pouvez définir l'origine dans votre réponse en fonction de la demande. De plus, ne pas oublier de mettre la tête Variez. En PHP Je procédez comme suit:

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

On peut aussi configurer dans le fichier Global.asax pour l'application 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 réponse semble être d'utiliser l'en-tête plus d'une fois. Autrement dit, plutôt que d'envoyer

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

envoyer

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

Sur Apache, vous pouvez le faire dans une section httpd.conf de <VirtualHost> ou d'un fichier en utilisant .htaccess mod_headers et cette syntaxe:

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"

L'astuce consiste à utiliser add plutôt que append comme premier argument.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top