Access-Control-Allow-Origin Несколько доменов происхождения?

Есть ли способ разрешить несколько кросс-доменов, используя заголовок Access-Control-Allow-Origin?

Я знаю о *, но он слишком открыт. Я действительно хочу разрешить только пару доменов.

Как пример, что-то вроде этого:

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

Я пробовал приведенный выше код, но он не работает в Firefox.

Можно ли указать несколько доменов или я застрял только на одном?

920
31 окт. '09 в 6:27
источник поделиться
28 ответов

Похоже, рекомендуемый способ сделать это - заставить ваш сервер читать заголовок Origin с клиента, сравнить его со списком доменов, которые вы хотели бы разрешить, и, если он совпадает, передать значение заголовка Origin обратно клиенту в качестве заголовка Access-Control-Allow-Origin в ответе.

С .htaccess вы можете сделать это так:

# ----------------------------------------------------------------------
# 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>
782
05 дек. '09 в 3:10
источник

Связанные вопросы


Похожие вопросы

Другое решение, которое я использую в 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");
}
191
17 сент. '11 в 13:49
источник

Это сработало для меня:

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

Когда положите в .htaccess, он будет работать наверняка.

102
18 июня '12 в 9:31
источник

У меня была та же проблема с woff-шрифтами, у нескольких поддоменов был доступ. Чтобы разрешить субдомены, я добавил что-то вроде этого в 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>

Для нескольких доменов вы можете просто изменить регулярное выражение в SetEnvIf.

85
18 мая '11 в 15:46
источник

Здесь, как повторить заголовок Origin, если он соответствует вашему домену с помощью Nginx, это полезно, если вы хотите обслуживать несколько поддоменов шрифта:

location /fonts {
    # this will echo back the origin header
    if ($http_origin ~ "example.org$") {
        add_header "Access-Control-Allow-Origin" $http_origin;
    }
}
59
13 сент. '12 в 23:25
источник

Вот что я сделал для приложения PHP, которое запрашивает 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);
}

Если запрашивающий источник разрешен моим сервером, верните сам $http_origin качестве значения заголовка Access-Control-Allow-Origin вместо возврата символа подстановки *.

22
26 дек. '12 в 0:48
источник

Есть один недостаток, о котором вам следует знать: как только вы выберете исходные файлы на CDN (или на любой другой сервер, который не позволяет создавать сценарии), или если ваши файлы кэшированы на прокси-сервере, изменение ответа на основе Заголовок запроса "Origin" не будет работать.

19
20 февр. '10 в 22:18
источник

Для нескольких доменов в вашем .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>
17
11 марта '14 в 19:51
источник

Для IIS 7.5+ с установленным модулем URL Rewrite 2.0 см. этот ответ SO

14
27 июня '15 в 4:57
источник

Для пользователей Nginx разрешить CORS для нескольких доменов. Мне нравится пример @marshall, хотя его антверпы соответствуют только одному домену. Для соответствия списку домена и поддомена это регулярное выражение облегчает работу со шрифтами:

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

Это будет отражать только заголовки "Access-Control-Allow-Origin", которые соответствуют указанному списку доменов.

14
10 янв. '15 в 21:31
источник

Вот решение для веб-приложения Java, основанное на ответе yesthatguy.

Я использую Джерси REST 1.x

Сконфигурируйте web.xml, чтобы знать о REST Джерси и 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>

Вот код для 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;
}

}
11
15 сент. '15 в 21:39
источник

Как упомянуто выше, Access-Control-Allow-Origin должен быть уникальным, а Vary должен быть установлен на Origin если вы находитесь за CDN (Content Delivery Network).

Соответствующая часть моей конфигурации 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';
}
9
09 нояб. '15 в 18:59
источник

Возможно, я ошибаюсь, но насколько я вижу, Access-Control-Allow-Origin имеет "origin-list" качестве параметра.

По определению 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

И из этого я утверждаю, что допускается различное происхождение, и оно должно быть разделено пробелами

7
10 окт. '12 в 14:40
источник

Я изо всех сил пытался настроить это для домена, использующего HTTPS, поэтому я решил, что смогу поделиться решением. Я использовал следующую директиву в файле 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>

Измените example.com на свое доменное имя. Добавьте это внутри <VirtualHost x.x.x.x:xx> в свой файл httpd.conf. Обратите внимание, что если ваш VirtualHost имеет суффикс порта (например, :80), эта директива не будет применяться к HTTPS, поэтому вам также нужно перейти в /etc/apache 2/sites-available/default-ssl и добавить тот же директивы в этом файле, внутри раздела <VirtualHost _default_:443>.

После обновления файлов конфигурации вам необходимо будет выполнить следующие команды в терминале:

a2enmod headers
sudo service apache2 reload
5
17 февр. '15 в 3:12
источник

Если у вас возникли проблемы со шрифтами, используйте:

<FilesMatch "\.(ttf|ttc|otf|eot|woff)$">
    <IfModule mod_headers>
        Header set Access-Control-Allow-Origin "*"
    </IfModule>
</FilesMatch>
4
06 июля '14 в 20:43
источник

Для приложений ExpressJS вы можете использовать:

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();
});
2
25 янв. '19 в 16:57
источник

Более гибкий подход заключается в использовании выражений Apache 2.4. Вы можете сопоставить домены, пути и практически все остальные переменные запроса. Хотя ответ * для всех, единственными, кто его получает, являются те, кто в любом случае отвечает требованиям.

<IfModule mod_headers.c>
    <If "%{HTTP:Host} =~ /\\bcdndomain\\.example$/i && %{HTTP:Origin} =~ /\\bmaindomain\\.example$/i">
        Header set Access-Control-Allow-Origin "*"
    </If>
</IfModule>
1
20 июля '18 в 8:50
источник

Чтобы облегчить многодоменный доступ для службы ASMX, я создал эту функцию в файле 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();
    }
}

Это также позволяет CORS обрабатывать глагол OPTIONS.

1
12 нояб. '16 в 2:59
источник

HTTP_ORIGIN не используется всеми браузерами. Насколько безопасен HTTP_ORIGIN? Для меня это пустое в FF.
У меня есть сайты, на которых я разрешаю доступ к моему сайту для отправки по идентификатору сайта, затем я проверяю свою БД для записи с этим идентификатором и получаю значение столбца SITE_URL (www.yoursite.com).

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

Даже если отправка по допустимому идентификатору сайта требует запроса из домена, указанного в моей БД, связанной с этим идентификатором сайта.

1
03 мая '13 в 18:39
источник

Здесь представлен расширенный вариант для apache, который включает в себя некоторые из последних и запланированных определений шрифтов:

<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>
1
26 февр. '15 в 23:46
источник

Для довольно простого копирования/вставки для приложений .NET я написал это, чтобы включить CORS из файла global.asax. Этот код следует советам, данным в принятом в настоящее время ответе, отражая происхождение, указанное в запросе в ответе. Это эффективно достигает "*" без его использования. Причина этого заключается в том, что он включает несколько других функций CORS, включая возможность отправки AJAX XMLHttpRequest с атрибутом withCredentials, установленным в значение 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" , "*");
    }
}
1
21 дек. '17 в 4:24
источник

И еще один ответ в Django. Чтобы иметь один вид, разрешающий CORS из нескольких доменов, вот мой код:

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
1
28 сент. '16 в 14:05
источник

Пример кода PHP для сопоставления поддоменов.

if( preg_match("/http:\/\/(.*?)\.yourdomain.example/", $_SERVER['HTTP_ORIGIN'], $matches )) {
        $theMatch = $matches[0];
        header('Access-Control-Allow-Origin: ' . $theMatch);
}
1
25 июня '13 в 10:53
источник

Ниже ответ специфичен для С#, но концепция должна быть применима ко всем различным платформам.

Чтобы разрешить перекрестные исходные запросы от веб-API, необходимо разрешить запросы Option для своего приложения и добавить примечание ниже на уровне контроллера.

[EnableCors (UrlString, Header, Method)] Теперь происхождение можно передавать только в виде строки. Поэтому, если вы хотите передать более одного URL-адреса в запросе, передайте его как разделенное запятыми значение.

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

0
15 марта '19 в 9:23
источник

Если вы попробуете так много примеров кода, как я, чтобы заставить его работать с помощью CORS, стоит упомянуть, что вам нужно сначала очистить кеш, чтобы попробовать, если он действительно работает, похожий на проблемы, например, когда старые изображения все еще присутствуют, даже если он удален на сервере (потому что он все еще сохраняется в вашем кеше).

Например, CTRL + SHIFT + DEL в Google Chrome для удаления кеша.

Это помогло мне использовать этот код, попробовав множество чистых решений .htaccess, и это казалось единственным работающим (по крайней мере для меня):

    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>

Также обратите внимание, что широко распространено множество решений, которые вы должны ввести Header set ..., но это Header add .... Надеюсь, что это помогает кому-то, испытывающему те же проблемы в течение нескольких часов, как я.

0
03 февр. '17 в 11:19
источник

Ответ службы поддержки Google на показ объявлений через SSL и грамматика в Сам RFC, похоже, указывает на то, что вы можете разграничить URL-адреса. Не уверен, насколько хорошо это поддерживается в разных браузерах.

0
18 окт. '13 в 15:39
источник

Мы также можем установить это в файле Global.asax для приложения Asp.net.

protected void Application_BeginRequest(object sender, EventArgs e)
    {

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

    }
-2
31 марта '15 в 14:59
источник

Ответ, похоже, заключается в использовании заголовка более одного раза. То есть вместо отправки

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

Отправить

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

В Apache вы можете сделать это в разделе httpd.conf <VirtualHost> или в файле .htaccess используя mod_headers и следующий синтаксис:

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"

Хитрость заключается в том, чтобы использовать в качестве первого аргумента add а не append.

-3
06 нояб. '10 в 1:22
источник

Посмотрите другие вопросы по меткам или Задайте вопрос