Contrôle D'Accès-Autoriser-Origine Domaines D'Origine Multiples?
y a-t-il un moyen d'autoriser plusieurs domaines croisés en utilisant l'en-tête Access-Control-Allow-Origin
?
je suis au courant du *
, mais il est trop ouvert. Je veux vraiment autoriser juste quelques domaines.
comme exemple, quelque chose comme ceci:
Access-Control-Allow-Origin: http://domain1.example, http://domain2.example
j'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?
26 réponses
sonne comme la façon recommandée de le faire est d'avoir votre serveur lire l'en-tête D'Origine du client, comparez cela à la liste des domaines que vous souhaitez autoriser, et si elle correspond, faire écho à la valeur de l'en-tête Origin
de retour 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)$">
<IfModule mod_headers.c>
SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.example|dev02.otherdomain.example)$" AccessControlAllowOrigin="151900920"
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header merge Vary Origin
</IfModule>
</FilesMatch>
une autre solution que J'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="151900920"
Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is
mis dans .htaccess
, il fonctionnera à coup sûr.
j'ai eu le même problème avec les polices woff, plusieurs sous-domaines devaient y avoir accès. Pour autoriser les sous-domaines, j'ai ajouté quelque chose comme ça à mon httpd.conf:
SetEnvIf Origin "^(.*\.example\.com)$" ORIGIN_SUB_DOMAIN=
<FilesMatch "\.woff$">
Header set Access-Control-Allow-Origin "%{ORIGIN_SUB_DOMAIN}e" env=ORIGIN_SUB_DOMAIN
</FilesMatch>
pour plusieurs domaines, vous pouvez simplement changer le regex dans SetEnvIf
.
Voici comment faire écho à L'en-tête Origin si elle correspond à votre domaine avec Nginx, c'est utile si vous voulez servir une police de 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 j'ai fait pour une application PHP qui est demandée 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 de la requête est autorisée par mon serveur, retournez le $http_origin
lui-même comme valeur de l'en-tête Access-Control-Allow-Origin
au lieu de retourner un joker *
.
il y a un inconvénient que vous devez savoir: dès que vous externalisez des fichiers vers un CDN (ou tout autre serveur qui ne permet pas le script) ou si vos fichiers sont mis en cache sur un proxy, modifier la réponse basée sur l'en-tête de requête "Origin" ne fonctionnera pas.
pour plusieurs domaines, dans votre .htaccess
:
<IfModule mod_headers.c>
SetEnvIf Origin "http(s)?://(www\.)?(domain1.example|domain2.example)$" AccessControlAllowOrigin="151900920"
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header set Access-Control-Allow-Credentials true
</IfModule>
Pour IIS 7.5+ avec Réécriture d'URL 2.0 module installé, veuillez voir la section cette SORTE de réponse
pour les utilisateurs de Nginx pour autoriser les CORS pour plusieurs domaines. J'aime l'exemple de @marshall bien que ses vers ne correspondent qu'à un domaine. Pour faire correspondre une liste de domaine et de sous-domaine, ce regex rend facile de travailler avec les 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 fera seulement écho aux en-têtes" Access-Control-Allow-Origin " qui correspondent à la liste de domaines donnée.
Voici une solution pour Java Web app, basée sur la réponse de yesthatguy.
J'utilise Jersey REST 1.x
configurer le web.xml pour être au courant de Maillot de REPOS et de la 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 défini à Origin
si vous êtes derrière un CDN (Content Delivery Network).
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 puisse voir Access-Control-Allow-Origin
a un "origin-list"
comme paramètre.
par définition an 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 là, je soutiens que différentes origines sont admises et devraient être espace séparé .
j'ai eu du mal à le configurer pour un domaine fonctionnant sous HTTPS, donc j'ai pensé que je partagerais la solution. J'ai utilisé la directive suivante dans mon httpd.conf fichier:
<FilesMatch "\.(ttf|otf|eot|woff)$">
SetEnvIf Origin "^http(s)?://(.+\.)?example\.com$" AccessControlAllowOrigin="151900920"
Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
</FilesMatch>
modifier example.com
pour votre nom de domaine. Ajoutez ceci dans <VirtualHost x.x.x.x:xx>
dans votre httpd.fichier conf . Notez que si votre VirtualHost
a un suffixe de port (par exemple :80
) alors cette directive ne s'appliquera pas à HTTPS, donc vous devrez allez aussi à /etc/apache2/sites-available / default-ssl et ajoutez la même directive dans ce fichier, à l'intérieur de la section <VirtualHost _default_:443>
.
une fois les fichiers de configuration mis à jour, vous devrez exécuter les commandes suivantes dans le terminal:
a2enmod headers
sudo service apache2 reload
si vous avez des problèmes avec les polices, utilisez:
<FilesMatch "\.(ttf|ttc|otf|eot|woff)$">
<IfModule mod_headers>
Header set Access-Control-Allow-Origin "*"
</IfModule>
</FilesMatch>
HTTP_ORIGIN n'est pas utilisé par tous les navigateurs. dans quelle mesure HTTP_ORIGIN est-il sécurisé? Pour moi il s'agit vide dans FF.
J'ai les sites que j'autorise l'accès à mon site Envoyer sur un ID de site, je vérifie ensuite ma DB pour l'enregistrement avec cet id 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 d'un ID de site valide la demande doit provenir du domaine indiqué dans ma base de données associée à celui-ci site ID.
Voici une option étendue pour apache qui inclut certaines des définitions de police les plus récentes et 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="151900920"
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header set Access-Control-Allow-Credentials true
</IfModule>
</FilesMatch>
et une autre réponse à Django. Pour avoir une vue unique autorise CORS de plusieurs 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 faciliter l'accès à plusieurs domaines pour un service ASMX, j'ai créé cette fonction dans le global.fichier 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 aussi la manipulation du verbe OPTIONS
par CORS.
de Google de soutien de réponse sur la diffusion d'annonces sur SSL et le la grammaire dans la RFC lui-même semblerait indiquer que vous pouvez délimiter l'espace de l'Url. Pas sûr de savoir comment bien pris en charge c'est dans les différents navigateurs.
si vous essayez tant d'exemples de code comme moi pour le faire fonctionner en utilisant CORS, il vaut la peine de mentionner que vous devez vider votre cache d'abord pour essayer si cela fonctionne réellement, similaire à des problèmes comme quand de vieilles images sont encore présentes, même si elle est supprimée sur le serveur (parce qu'elle est toujours sauvegardée dans votre cache).
par exemple CTRL + SHIFT + DEL dans Google Chrome pour supprimer votre cache.
cela m'a aidé à utiliser ce code après avoir essayé de nombreuses solutions pures .htaccess
et cela semblait le seul travail (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="151900920"
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
</IfModule>
</FilesMatch>
notez également qu'il est largement répandu que de nombreuses solutions disent que vous devez taper Header set ...
mais il est Header add ...
. J'espère que ça aidera quelqu'un qui a les mêmes problèmes depuis des heures, comme moi.
pour un copier / coller assez facile pour les applications .NET, j'ai écrit ceci pour activer CORS à l'intérieur d'un global.fichier asax. Ce code suit les conseils donnés dans la réponse actuellement acceptée, reflétant quelle que soit l'origine de retour est donnée dans la demande dans la réponse. Ce bien un '*' sans l'utiliser. La raison en est qu'il permet plusieurs autres fonctionnalités de CORS, y compris la possibilité d'envoyer un Ajax XMLHttpRequest avec l'attribut 'withCredentials' défini à '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" , "*");
}
}
une approche plus souple consiste à utiliser les expressions D'Apache 2.4. Vous pouvez faire la correspondance avec les domaines, les chemins, et à peu près toutes les autres variables de requête. Bien que la réponse soit *
pour tous, les seuls demandeurs qui reçoivent cette réponse sont ceux qui satisfont de toute façon aux exigences.
<IfModule mod_headers.c>
<If "%{HTTP:Host} =~ /\byourdomain\.example$/i">
Header set Access-Control-Allow-Origin "*"
</If>
</IfModule>
exemple de code PHP pour les sous-domaines correspondants.
if( preg_match("/http:\/\/(.*?)\.yourdomain.example/", $_SERVER['HTTP_ORIGIN'], $matches )) {
$theMatch = $matches[0];
header('Access-Control-Allow-Origin: ' . $theMatch);
}
, 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
<VirtualHost>
ou .htaccess
en utilisant 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 est d'utiliser add
plutôt que append
comme premier argument.
on peut aussi mettre ça dans Global.fichier asax pour Asp.net application.
protected void Application_BeginRequest(object sender, EventArgs e)
{
// enable CORS
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "https://www.youtube.com");
}