Access-Control-Allow-Origin Домены нескольких источников? - PullRequest
946 голосов
/ 31 октября 2009

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

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

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

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

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

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

Ответы [ 28 ]

11 голосов
/ 15 сентября 2015

Вот решение для веб-приложения 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;
}

}
9 голосов
/ 09 ноября 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';
}
7 голосов
/ 10 октября 2012

Возможно, я ошибаюсь, но, насколько я вижу, 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

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

5 голосов
/ 17 февраля 2015

Я изо всех сил пытался настроить это для домена, использующего 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
4 голосов
/ 06 июля 2014

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

<FilesMatch "\.(ttf|ttc|otf|eot|woff)$">
    <IfModule mod_headers>
        Header set Access-Control-Allow-Origin "*"
    </IfModule>
</FilesMatch>
2 голосов
/ 25 января 2019

Для приложений 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();
});
1 голос
/ 26 февраля 2015

Вот расширенный вариант для 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 голос
/ 25 июня 2013

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

if( preg_match("/http:\/\/(.*?)\.yourdomain.example/", $_SERVER['HTTP_ORIGIN'], $matches )) {
        $theMatch = $matches[0];
        header('Access-Control-Allow-Origin: ' . $theMatch);
}
1 голос
/ 03 мая 2013

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

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

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

1 голос
/ 21 декабря 2017

Для довольно простого копирования / вставки для приложений .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" , "*");
    }
}
...