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

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

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

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

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

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

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

+953
31 окт. '09 в 3:27
источник поделиться
29 ответов

Похоже, рекомендуемый способ сделать это - заставить ваш сервер читать заголовок 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>
+803
05 дек. '09 в 0: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");
}
+199
17 сент. '11 в 10: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, он будет работать наверняка.

+104
18 июн. '12 в 6: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.

+86
18 мая '11 в 12: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;
    }
}
+60
13 сент. '12 в 20: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 вместо возврата символа подстановки *.

+24
25 дек. '12 в 21:48
источник

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

+19
20 февр. '10 в 19: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>
+18
11 мар. '14 в 16:51
источник

Для пользователей 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", которые соответствуют указанному списку доменов.

+15
10 янв. '15 в 18:31
источник

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

+14
27 июн. '15 в 1:57
источник

Вот решение для веб-приложения 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 в 18: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 в 15: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 в 11: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 в 0:12
источник

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

<FilesMatch "\.(ttf|ttc|otf|eot|woff)$">
    <IfModule mod_headers>
        Header set Access-Control-Allow-Origin "*"
    </IfModule>
</FilesMatch>
+4
06 июл. '14 в 17: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 в 13:57
источник

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

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

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

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

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

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

Для довольно простого копирования/вставки для приложений .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 в 1:24
источник

Здесь представлен расширенный вариант для 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 в 20:46
источник

Более гибкий подход заключается в использовании выражений 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 в 5: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
11 нояб. '16 в 23:59
источник

И еще один ответ в 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 в 11:05
источник

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

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

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

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

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

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

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

Если вы попробуете так много примеров кода, как я, чтобы заставить его работать с помощью 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 в 8:19
источник

Для заголовка Access-Control-Allow-Origin можно указать только один источник. Но вы можете установить источник в вашем ответе в соответствии с запросом. Также не забудьте установить заголовок Vary. В PHP я бы сделал следующее:

    /**
     * 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
  }
0
25 июл. '19 в 10:52
источник

Мы также можем установить это в файле 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 в 11: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.

-4
05 нояб. '10 в 22:22
источник

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