Access-Control-Allow-Origin с несколькими исходными доменами?

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

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

Например, примерно так:

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

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

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


person Thomas J Bradley    schedule 31.10.2009    source источник
comment
При использовании последней версии Firefox домены, разделенные запятыми или пробелами, не работали. Сопоставление со списком доменов и размещение одного хоста в заголовках по-прежнему обеспечивает лучшую безопасность и работает правильно.   -  person Daniel W.    schedule 26.03.2014
comment
Если вы боретесь с этим для HTTPS, я нашел решение .   -  person Alex W    schedule 17.02.2015
comment
@sam или *? shared based by returning the value of the Origin request header, "*", or "null"   -  person The Red Pea    schedule 30.09.2017
comment
важное примечание: разрешение создавать только домены в заголовке Access-Control-Allow-Origin не означает, что другие домены не могут запускать метод на этой конечной точке (например, метод REST API ). Это просто означает, что запрещенные источники не могут использовать результат в javascript (это гарантирует браузер). Для ограничения доступа к конечной точке для определенных доменов используйте фильтр запросов на стороне сервера, например возвращает HTTP 401 для запрещенных доменов.   -  person klues    schedule 21.11.2018
comment
Вы всегда должны добавлять заголовок Vary: Origin, если хотите использовать несколько URL-адресов, см .: https://fetch.spec.whatwg.org/#cors-protocol-and-http-caches   -  person Null    schedule 07.06.2019


Ответы (32)


Похоже, что рекомендуемый способ сделать это - попросить ваш сервер прочитать заголовок 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>
person yesthatguy    schedule 05.12.2009
comment
Как бы вы добавили поддомены с подстановочными знаками, например: *.example.com, или порты с подстановочными знаками, например: localhost:* - person Ben Winding; 23.02.2021
comment
Для тех, кому интересно, вы можете сделать (.+\.google.com) вместо (google.com|staging.google.com) - person Ben Winding; 17.03.2021

Другое решение, которое я использую в 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");
}
person Nikolay Ivanov    schedule 17.09.2011

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

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 точно заработает.

person Jay Dave    schedule 18.06.2012

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

person Staugaard    schedule 18.05.2011

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

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

Вот что я сделал для приложения 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 вместо того, чтобы возвращать подстановочный знак *.

person Rakib    schedule 25.12.2012
comment
Вероятно, следует проверить, существует ли $request_headers['Origin'];, иначе любые прямые запросы будут вызывать E_NOTICE. - person MrWhite; 12.01.2021

Для приложений 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();
});
person eyecatchUp    schedule 25.01.2019

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

person Mark    schedule 20.02.2010

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

person Adriano Rosa    schedule 10.01.2015
comment
Будьте осторожны: nginx.com/resources/wiki/start/topics/ depth / ifisevil - person Almenon; 18.03.2021

Для нескольких доменов в вашем .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>
person George    schedule 11.03.2014
comment
Большой. Помог мне. - person Ahmad Vaqas Khan; 21.03.2021

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

person Paco Zarate    schedule 27.06.2015

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

Соответствующая часть моей конфигурации 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';
}
person hernvnc    schedule 09.11.2015

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

Я использую Jersey REST 1.x

Настройте web.xml, чтобы знать о Jersey 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;
}

}
person duvo    schedule 15.09.2015

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

Согласно определению 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

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

person drAlberT    schedule 10.10.2012

Я изо всех сил пытался настроить это для домена, работающего по протоколу 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 / apache2 / sites-available / default-ssl и добавьте ту же директиву в этот файл внутри раздела <VirtualHost _default_:443>.

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

a2enmod headers
sudo service apache2 reload
person Alex W    schedule 17.02.2015
comment
Мне нравится этот вариант, и я объединил / модифицировал его с реализацией @George. Иногда на серверах нет доступного a2enmod, поэтому все, что вам нужно сделать, это проверить свой основной httpd.conf, чтобы увидеть, не закомментирована ли строка: LoadModule headers_module modules / mod_headers.so. - person Mike Kormendy; 26.02.2015
comment
У моего источника был номер порта, поэтому я изменил регулярное выражение, включив его: ^http(s)?://(.+\.)?example\.com(:\d+)?$ - person indiv; 02.05.2015

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

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

Код PHP:

$httpOrigin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : null;
if (in_array($httpOrigin, [
    'http://localhost:9000', // Co-worker dev-server
    'http://127.0.0.1:9001', // My dev-server
])) header("Access-Control-Allow-Origin: ${httpOrigin}");
header('Access-Control-Allow-Credentials: true');
person Liakos    schedule 23.01.2020

Вот расширенный вариант для 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>
person Mike Kormendy    schedule 26.02.2015

Чтобы упростить копирование / вставку для приложений .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" , "*");
    }
}
person QA Collective    schedule 21.12.2017

AWS Lambda / API-шлюз

Для получения информации о том, как настроить несколько источников на бессерверном AWS Lambda и API Gateway (хотя это довольно крупное решение для чего-то, что, как кажется, должно быть довольно простым), см. Здесь:

https://stackoverflow.com/a/41708323/1624933


В настоящее время невозможно настроить несколько источников в API Gateway, см. Здесь: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html), но рекомендация (в ответе выше) такова:

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

Простое решение, очевидно, включает ALL (*) следующим образом:

exports.handler = async (event) => {
    const response = {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS
        },
        body: JSON.stringify([{

Но может быть лучше сделать это на стороне шлюза API (см. Вторую ссылку выше).

person timhc22    schedule 23.03.2020
comment
Access-Control-Allow-Credentials: true не допускается с подстановочным знаком Access-Control-Allow-Origin: *. Вместо этого установите конкретный <origin>. - person Tom; 18.04.2020
comment
@Tom, да, не уверен, почему это было там, я не могу вспомнить, но я мог скопировать его из значений по умолчанию, которые были добавлены в AWS? Спасибо, что указали на это. - person timhc22; 20.04.2020

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

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

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

person mathius1    schedule 03.05.2013

Чтобы упростить доступ к нескольким доменам для службы 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 глагол.

person Derek Wade    schedule 11.11.2016

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

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

И еще один ответ в 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
person Silvain    schedule 28.09.2016

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

person Bob Aman    schedule 18.10.2013
comment
"показ объявлений через SSL" - ссылки на спецификацию w3 .org / TR / cors / # access-control-allow-origin-response-header, который добавляет примечание. На практике производство origin-list-or-null более ограничено. Вместо того, чтобы разрешать список источников, разделенных пробелами, это либо одиночное происхождение, либо строка null. - person spazm; 29.04.2015
comment
Хотя важно отметить эту деталь, когда в спецификации говорится «На практике», это не означает, что это допустимо только так. Это означает, что если вы сделаете это таким образом, вы можете столкнуться с проблемами, потому что большинство разработчиков либо неправильно, либо не полностью реализуют спецификацию. Спецификация допускает разделенный пробелами список источников происхождения, который вы можете увидеть здесь, в EBNF, в разделе origin-list: tools.ietf.org/html/rfc6454#section-7.1 - person Bob Aman; 04.05.2015

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

person AlexioVay    schedule 03.02.2017

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

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

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

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

person sakshi agrawal    schedule 15.03.2019

Для заголовка 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
  }
person Simon    schedule 25.07.2019

У меня https://stackoverflow.com/a/7454204/13779574 этот код работал хорошо, но выдает ошибку, когда пользователь попадает на эту страницу. Я исправил эту проблему с помощью этого кода.

if (isset($_SERVER['HTTP_ORIGIN'])) {
   $http_origin = $_SERVER['HTTP_ORIGIN'];
   if ($http_origin == "http://localhost:3000" || $http_origin == "http://api.loc/"){  
      header("Access-Control-Allow-Origin: $http_origin");
   }
}
person Bekorchi Bekorchiyevich Bekaro    schedule 13.04.2021

Я тоже столкнулся с той же проблемой. мой клиент был на 9097, шлюз api на 9098, микросервис на .... На самом деле я использовал весенний облачный шлюз Api
в моем yml файле шлюза, я разрешил перекрестное происхождение, например ... allowedOrigins: http: // localhost: 9097

также в моем микросервисе я использовал @crossOrigin

когда клиент отправлял запрос на шлюз api, в ответ приходили два заголовка Access-Control-Allow-Origin [один из файла api yml и один из микросервиса @crossorigin], поэтому браузер заблокировал запрос

я решил это как ...

    @Bean
public RouteLocator getRL(RouteLocatorBuilder builder) {
    
return  builder.routes()
    
        .route(p-> 
         "/friendlist","/guest/**"
                )
         .filters(f ->{
             //f.removeResponseHeader("Access-Control-Allow-Origin");
             //f.addResponseHeader("Access-Control-Allow-Origin","http://localhost:9097");
             f.setResponseHeader("Access-Control-Allow-Origin","http://localhost:9097");
             return f;
         })
        .uri("lb://OLD-SERVICE")
        
        
    ).build();      
}
person akhil    schedule 06.05.2021

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

    }
person sudhAnsu63    schedule 31.03.2015

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

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 в качестве первого аргумента.

person Ben C. Forsberg    schedule 05.11.2010
comment
Уловка выглядит многообещающей, но в FF 3.6.13 она не работает. Я наблюдаю, что два заголовка с одинаковым именем объединяются в один, а значения разделяются запятой - и это не работает, как опубликовал OP. Я заметил заголовки в LiveHTTPHeaders и FireBug. - person pwes; 10.02.2011
comment
Видите ли, когда я это сделал, я установил заголовок ... вместо добавления заголовка ... - похоже, у меня работает. Firefox 3.6.16 - person B T; 05.04.2011
comment
Это запрещено и не работает в FF - bugzilla.mozilla.org/show_bug.cgi ? id = 671608 - person Sairam; 27.08.2012
comment
есть вариант, который, кажется, работает: stackoverflow.com/questions/9466496/ - person Jack James; 28.04.2013
comment
Просто потратил два часа, пытаясь исправить проблему, связанную с CORS, и оказалось, что это произошло из-за нескольких заголовков Access-Control-Allow-Origin. Я удалил несколько заголовков Access-Control-Allow-Origin, и он начал работать. Так что это неправильный ответ, несмотря на количество голосов. Вместо этого используйте этот метод для поддержки нескольких доменов: stackoverflow.com/a/1850482/123545 - person ErJab; 25.05.2013
comment
Фактически, вы получите сообщение об ошибке в журнале последней версии браузера Chrome на данный момент, говорящее вам, что он игнорирует заголовок Access-Control-Allow-Origin, потому что существует несколько значений. - person Danger; 25.04.2014
comment
Неа. Из developer.mozilla.org/en-US/docs/Web/HTTP / Access_control_CORS: возвращаемый ресурс может иметь один заголовок Access-Control-Allow-Origin .. и из w3.org/TR/cors/#access-control-allow-origin-response-header: вместо того, чтобы разрешать список источников, разделенных пробелами, это либо одно происхождение, либо строка null (сначала я слышал о null здесь, кстати) - person AlexChaffee; 10.06.2014
comment
В спецификациях четко сказано, что несколько значений приведут к сбою алгоритма CORS. Так что это неправильно. - person Lior; 08.09.2014
comment
Также подтверждение, что это неверно. Используя это для обслуживания CSS для четырех доменов, я получаю сообщение об ошибке в журнале Chrome [...]. Заголовок содержит несколько значений aaa .com, bbb.com ', но разрешен только один. Не имеет значения, определяете ли вы его как один заголовок, или несколько, или используя add или set. Это просто не работает. - person Radley Sustaire; 08.10.2014