Programing

Access-Control-Allow-Origin 다중 원본 도메인?

lottogame 2020. 9. 28. 07:54
반응형

Access-Control-Allow-Origin 다중 원본 도메인?


Access-Control-Allow-Origin헤더를 사용하여 여러 교차 도메인을 허용하는 방법이 있습니까?

를 알고 *있지만 너무 열려 있습니다. 정말 몇 개의 도메인 만 허용하고 싶습니다.

예를 들면 다음과 같습니다.

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

위의 코드를 시도했지만 Firefox에서 작동하지 않는 것 같습니다.

여러 도메인을 지정할 수 있습니까? 아니면 하나만 붙어 있습니까?


권장되는 방법은 서버가 클라이언트에서 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>

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

이것은 나를 위해 일했습니다.

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확실히 작동합니다.


나는 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.


도메인이 Nginx와 일치하는 경우 Origin 헤더를 다시 에코하는 방법은 다음과 같습니다. 여러 하위 도메인에 글꼴을 제공하려는 경우 유용합니다.

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

다음은 AJAX에서 요청하는 PHP 애플리케이션에 대해 수행 한 작업입니다.

$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를 반환합니다 *.


주의해야 할 한 가지 단점이 있습니다. 파일을 CDN (또는 스크립팅을 허용하지 않는 다른 서버)에 아웃소싱하거나 파일이 프록시에 캐시되는 즉시 '원본'에 따라 응답을 변경합니다. 요청 헤더가 작동하지 않습니다.


여러 도메인의 경우 .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>

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"헤더 만 에코합니다.


URL Rewrite 2.0 모듈이 설치된 IIS 7.5+의 경우이 SO 답변을 참조하십시오.


다음은 yesthatguy의 답변을 기반으로 한 Java 웹 앱 솔루션입니다.

Jersey REST 1.x를 사용하고 있습니다.

Jersey REST 및 CORSResponseFilter를 인식하도록 web.xml 구성

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

}

위에서 언급 한대로 Access-Control-Allow-Origin고유 Vary해야하며 OriginCDN (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';
}

내가 틀렸을 수도 있지만 내가 볼 수 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

그리고 이것으로부터 나는 다른 기원이 인정되고 공백으로 분리 되어야한다고 주장한다 .


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도메인 이름으로 변경하십시오 . httpd.conf 파일 <VirtualHost x.x.x.x:xx>이것을 추가 하십시오. 당신이 경우 통지 포트 접미사 (예를 들어이있다 ) 당신은 또한에 갈 필요가 있도록 다음이 지시어는, HTTPS에 적용되지 않습니다 / 등은 / 아파치 / 사이트-가능 / 기본-SSL 및 해당 파일 내부에 같은 지시문을 추가 의 섹션을 참조하십시오.VirtualHost:80<VirtualHost _default_:443>

구성 파일이 업데이트되면 터미널에서 다음 명령을 실행해야합니다.

a2enmod headers
sudo service apache2 reload

글꼴에 문제가있는 경우 다음을 사용하십시오.

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

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();
});

HTTP_ORIGIN is not used by all browsers. How secure is HTTP_ORIGIN? For me it comes up empty in FF.
I have the sites that I allow access to my site send over a site ID, I then check my DB for the record with that id and get the SITE_URL column value (www.yoursite.com).

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

Even if the send over a valid site ID the request needs to be from the domain listed in my DB associated with that site ID.


Here's an expanded option for apache that includes some of the latest and planned font definitions:

<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>

And one more answer in Django. To have a single view allow CORS from multiple domains, here is my 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

For a fairly easy copy / paste for .NET applications, I wrote this to enable CORS from within a global.asax file. This code follows the advice given in the currently accepted answer, reflecting whatever origin back is given in the request into the response. This effectively achieves '*' without using it. The reason for this is that it enables multiple other CORS features, including the ability to send an AJAX XMLHttpRequest with the 'withCredentials' attribute set to '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" , "*");
    }
}

To facilitate multiple domain access for an ASMX service, I created this function in the global.asax file:

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();
    }
}

This allows for CORS handling of OPTIONS verb also.


PHP code example for matching subdomains.

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

A more flexible approach is to use Apache 2.4's expressions. You can match against domains, paths, and just about every other request variable. Though the response is * for all, the only requesters receiving that response are the ones that meet the requirements anyway.

<IfModule mod_headers.c>
    <If "%{HTTP:Host} =~ /\\bcdndomain\\.example$/i && %{HTTP:Origin} =~ /\\bmaindomain\\.example$/i">
        Header set Access-Control-Allow-Origin "*"
    </If>
</IfModule>

Google's support answer on serving ads over SSL and the grammar in the RFC itself would seem to indicate that you can space delimit the URLs. Not sure how well-supported this is in different browsers.


If you try so many code examples like me to make it work using CORS, it is worth to mention that you have to clear your cache first to try if it actually works, similiar to issues like when old images are still present, even if it's deleted on the server (because it is still saved in your cache).

For example CTRL + SHIFT + DEL in Google Chrome to delete your cache.

This helped me using this code after trying many pure .htaccess solutions and this seemed the only one working (at least for me):

    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>

Also note that it is widely spread that many solutions say you have to type Header set ... but it is Header add .... Hope this helps someone having the same troubles for some hours now like me.


Below answer is specific to C#, but the concept should be applicable to all the different platforms.

To allow Cross Origin Requests from a web api, You need to allow Option requests to your Application and Add below annotation at controller level.

[EnableCors(UrlString,Header, Method)] Now the origins can be passed only a s string. SO if you want to pass more than one URL in the request pass it as a comma seperated value.

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


Only a single origin can be specified for the Access-Control-Allow-Origin header. But you can set the origin in your response according to the request. Also don't forget to set the Vary header. In PHP I would do the following:

    /**
     * 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
  }

We can also set this in Global.asax file for 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");

    }

The answer seems to be to use the header more than once. That is, rather than sending

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

send

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

On Apache, you can do this in an httpd.conf <VirtualHost> section or .htaccess file using mod_headers and this syntax:

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"

The trick is to use add rather than append as the first argument.

참고URL : https://stackoverflow.com/questions/1653308/access-control-allow-origin-multiple-origin-domains

반응형