출입 통제 허용 원산지 도메인?


1049

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

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

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

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

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

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



3
최신 Firefox를 사용하면 쉼표로 구분되거나 도메인으로 구분되지 않았습니다. 도메인 목록과 일치하고 헤더에 단일 호스트를 배치하는 것이 여전히 보안이 우수하고 제대로 작동합니다.
Daniel W.

1
HTTPS에 대해이 문제로 어려움을 겪고 있다면 해결책을 찾았습니다 .
Alex W

7
중요 사항 :Access-Control-Allow-Origin헤더에cretain 도메인 만 허용한다고해서 다른 도메인이이 엔드 포인트에서 메소드를 트리거 할 수 없다는 의미는 아닙니다 (예 : REST API 메소드). 허용되지 않는 출처는 자바 스크립트에서 결과를 사용할 수 없다는 것을 의미합니다 (브라우저가 이것을 보장합니다). 특정 도메인의 엔드 포인트에 대한 액세스를 제한하려면 허용되지 않는 도메인에 대해 HTTP 401을 반환하는 서버 측 요청 필터를 사용하십시오.
klues

1
Vary: Origin여러 URL을 사용하려면 항상 헤더를 추가해야합니다 . fetch.spec.whatwg.org/#cors-protocol-and-http-caches
Null

답변:


861

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

41
이것은 W3C가 제안한 것과 일치한다 -w3.org/TR/cors/#access-control-allow-origin-response-hea
Simon B.

153
이 답변의 내 문제는 CDN을 사용하기 때문에 실제로 도움이되지 않는다는 것입니다 .CDN이 프로그래밍 방식으로 헤더를 설정하는 방법을 제어 할 수는 없습니다.
BT

6
- 내 대답은 아래의 실제 예 (Nginx에) stackoverflow.com/a/12414239/6084
mjallday

71
캐시 또는 CDN이 문제가되는 경우 Vary 헤더 를 사용 하여 캐시 / CDN에 서로 다른 Origin 요청 헤더 값에 대한 별도의 응답을 유지하도록 지시하십시오. 응답에 "Vary : Origin"과 같은 헤더를 포함시킵니다. 그런 다음 캐시 / CDN은 헤더가 "Origin : foo.example.com "인 요청에 대해 하나의 응답을 보내고 헤더가 "Origin : bar.example.com "인 요청에 대해 다른 응답을 보내야한다는 것을 알고 있습니다.
Sean

10
@saturdayplace, Origin 헤더에 액세스 할 수 있으면 CORS를 지난 것입니다.
Paul Draper

222

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

12
stackoverflow.com/a/1850482/11635 에서 제안 된 접근법을 사용 하지 않습니까? (와일드 카드를 보내지 말고 요청한 오리진 만 보냈습니까)? 더 이상 아무것도 달성하지 않고 더 관대 한 것입니까?
Ruben Bartelink

15
가진 header('Access-Control-Allow-Origin: *')때로는 자격 증명 플래그가 true 인 경우 와일드 카드를 사용할 수 없다고하는 것은 - 때 발생하는 header('Access-Control-Allow-Credentials: true')아마. 따라서 $http_origin조건이 충족되면 자체 를 Allow-Origin하는 것이 좋습니다.
Rakib

6
와 마지막 줄 대체 header("Access-Control-Allow-Origin: " . $http_origin);작동하도록
프랑수아 로맹

2
이 코드는 HTTP_ORIGIN 헤더가 인식되지 않으면 Access-Control-Allow-Origin이 전혀 설정되지 않아 스크립트가 열린 상태로 유지된다는 점에서 결함이있는 것으로 보입니다.
Stephen R

9
@StephenR은 실제로 "와이드 클로즈"가 더 정확할 것입니다. 이것이 목적은 다른 도메인에 스크립트를 여는 것입니다.)
Kaddath

113

이것은 나를 위해 일했다 :

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


24
나에게 가장 좋은 해결책이지만 포트 지원을 추가했습니다 (예 : 개발을 위해 localhost : 3000 ) : SetEnvIf Origin "^ http (s)? : // (. + \.)? (localhost | stackoverflow.com | example1.com) ( : [0-9] +)? $ "origin_is = $ 0
vszurma

2
stackoverflow와 관련된 몇 가지 답변 중 이것이 효과적이었습니다.
Meetai.com

내가 추가 할 필요 Header set Access-Control-Allow-Credentials true@George의 대답과 같은 일이에 대한
99 문제 - 구문은 아니다

Origin을 사용할 때 확실히 작동합니다. 그러나 경우에 따라 Origin은 일부 요청에서 사용할 수 없으며 브라우저마다 다릅니다. 그런 다음 Referer대신 대신 사용하기로 결정했습니다 Origin. 사용 Referer일을하지만 문제는에 전체 URL을 다시 설정하는 것입니다 Access-Control-Allow-Origin내가 밖으로 도메인 이름을 잘라 원하는 Referer과에 할당합니다 Access-Control-Allow-Origin. 이 echo http://example.com/index.php/ab/cd | cut -d'/' -f1,2,3bash 명령 의 결과와 같은 것이 있습니다 . (apache) conf 파일에서 동일한 작업을 수행 할 수 있습니까? 어떤 아이디어?
3AK

1
이것은 나를 위해 작동하지 않습니다. 2 줄을 추가 할 때 항상 코드 500 오류가 발생합니다. 실제로 PHP 5.6.15 사용
BoCyrill

91

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.


4
트릭을 했어. 정규식을 올바르게 적용하십시오. 도메인 자체 (예 : (.*\.?example\.org)for example.com및) 를 허용하려면 물음표를 추가해야했습니다 sub.example.com.
trkoch

3
이것을 IIS 7에 적용하는 방법에 대한 생각이 있습니까?
Mark

그래도 목적을 이기지 않습니까? 악의적 인 사용자가 Origin 헤더 값을 위조하는 것을 어떻게 막을 수 있습니까?
그레고리 조셉

1
@ GrégoryJoseph Access-Control-Allow-Origin은 요청할 수있는 사람으로부터 리소스를 숨기는 것이 아닙니다. 악의적 인 사이트가 최종 사용자가 귀하의 사이트를 호출하지 못하도록 막는 것입니다. 글꼴 파일의 경우 글꼴의 핫 링크를 효과적으로 제한 할 수 있습니다. 왜 글꼴 (mozilla / firefox)이 다른 리소스 (js, css 등)에 대해 동일한 작업을 수행하지 않았습니까?
트래커 1

@trkoch, 정규식에 버그가 있습니다 subexample.com. 또한 허용 됩니다. 다음과 같이 변경해야합니다.((.*\.)?example\.org)
bluesmoon

65

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

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

다음과 다른 점을 이해할 수 없습니다. add_header Access-Control-Allow-Origin *; 설명 할까?
Anoyz

그러면 브라우저가 지정된 도메인에서만 요청을 보낼 수있는 권한을 부여하는 헤더가 반환됩니다. 브라우저에서 해당 페이지에로드 된 다른 도메인의 콘텐츠가 서버에 액세스 할 수있는 권한을 부여 할 수 있다고 생각합니다.
mjallday

7
@Anoyz "Allow *"가 허용되지 않는 보안이 강화 될 수 있지만 허용 헤더에 대해 지정된 일치하는 호스트 이름이 작동합니다. 예를 들어, 도메인 간 인증 정보를 보내려면 "Allow *"를 사용할 수 없습니다.
TCC

3
는 IS .example.org에서이 정규 표현식이기 때문에 어떤 값으로 해석? 어떤 경우에 이것은 실수로 커스텀 example-org TLD를 허용합니까?
stuckj

1
올바른 정규 표현식은 "^example\.org$"해커가 정규 표현식을 통해 subdomainexample.org(사용 ^) 또는 example.orgevil(사용 $) 또는 examplezorg(탈출 \.) 하지 못하도록해야하기 때문입니다
zeg

27

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


20

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


4
이것에 대해 자세히 설명해 주시거나 더 많은 정보를 찾을 수있는 곳을 알려주시겠습니까? Limelight를 사용하여이 작업을 수행하려고합니다. 여러분이 틀 렸으면합니다. 기술 담당자 중 한 명이 CDN 시드 서버가 헤더를 보내면 CDN 자체가 헤더를 보냅니다. 아직 테스트하지 않았습니다
BT

12
캐시 또는 CDN이 문제가되는 경우 Vary 헤더를 사용하여 캐시 / CDN에 서로 다른 Origin 요청 헤더 값에 대해 별도의 응답을 유지하도록 지시하십시오. 응답에 "Vary : Origin"과 같은 헤더를 포함시킵니다. 그런 다음 캐시 / CDN은 헤더가 "Origin : foo.example.com "인 요청에 대해 하나의 응답을 보내고 헤더가 "Origin : bar.example.com "인 요청에 대해 다른 응답을 보내야한다는 것을 알고 있습니다.
Sean

Vary: Origin 가장 큰 CDN 중 하나 인 Akamai는 지원하지 않습니다 ... 자세한 내용은 여기를 참조하십시오
Brad Parks

20

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

4
이 스 니펫은 저에게 완벽하게 작동합니다. 그러나 나는 그것이 무엇을하는지 이해하지 못한다 : D
Karl Adler

2
나는 '^'즉 ...한다 SetEnvIf 기원 "을 추가했다 있지만,이, 나를 위해 일한 ^ HTTP (S) : // WWW (\.)?
gypsyDev

stackoverflow.com/a/14034228/209139 와 거의 동일합니다 . 단지 .htaccess 구문이 PHP보다 읽기가 훨씬 어렵다는 것입니다. Header set Vary Origin이 답변에 좋은 추가가 될 것입니다.
TRiG

1
도움을 주셔서 감사합니다
Cool Perfectionist

2
로 변경 AccessControlAllowOrigin=$0$1해야했습니다 AccessControlAllowOrigin=$0. 그렇지 않으면 HTTPS 원본에서 작동하지 않았습니다. http://example.com올바르게 나왔지만 끝에 추가로와 https://example.com같이 나왔습니다 . https://example.comss
TRiG

17

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


domain3.com.badhacker.com에 액세스가 허용되므로 \ z로 마지막에 정규식을 잠글 필요가 있다고 생각하십시오.
dft

@dft 우리는 마지막에 $를 정의합니다
Adriano Rosa

미안 요점 예제에서 의미 @AdrianoRosa에 의해 실제 포스트는 \ Z와 같은 일을
DFT


13

다음은 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;
}

}

위의 링크가 만료되었습니다. 새 링크를 추가하거나 자세한 내용으로 답변을 업데이트 할 수 있습니다. 감사
RajKumar Samala

자세한 내용을 추가했습니다. 도움이 되길 바랍니다
duvo

12

위에서 언급했듯이 CDN (Content Delivery Network) 뒤에있는 경우 Access-Control-Allow-Origin고유 Vary해야합니다 Origin.

내 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';
}

set $cors숨겨진 의미의 어떤 종류의, 또는 당신의 conifg 단지 특정입니까? 그것은 두 번째와 함께 생략 될 수있는 것 같습니다if
mikezter

맞습니다. 헤더를 설정하기 위해 테스트 한 유일한 조건이라면 생략 할 수 있습니다. 내 구성에 여러 개가 있습니다.
hernvnc

9

어쩌면 내가 틀렸을 수도 있지만, 내가 알 수 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

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


2
그것은 스펙의 올바른 해석 인 것 같습니다. 즉, 사양은 현재 브라우저에서 완벽하게 지원되지 않는 것 같습니다 (예를 들어 Firefox 17.0에서 테스트하여 작동하지 않음을 확인했습니다).
Rick Riensche

7
CORS 사양5.1 Access-Control-Allow-Origin Response Header출처리스트가 제한되는 상태 : 오히려 기원의 공간 분리 된 목록을 허용하는 것보다, 그것 중 하나의 기원 또는 문자열 "널 (null)"이다.
maxpolk

2
내 답변에 대한 의견에서 언급했듯이 RFC 2119 요구 사항이 아닌 구현 자 메모의 일부입니다. '올바른'답변은 공백으로 구분 된 값을 사용하는 것입니다. 문제는 단순히 구현이 불완전하기 때문에 '올바른'답변이 반드시 작동하지는 않는다는 것입니다. 그것은해야하지만 그렇지 않습니다. 그러나 앞으로는 구현이 개선 될수록 변경 될 수 있습니다.
밥 아만

8

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

이 모든 다른 호출을 허용하는 호출 다음에 ...
Ievgen Naida

@IevgenNaida 그래서? 무엇이 문제입니까?
eyecatchUp

7

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

나는이 옵션을 좋아하고 @George의 구현과 결합 / 수정했다. 때로는 서버에 사용 가능한 a2enmod가 없으므로 Main httpd.conf에서 LoadModule headers_module modules / mod_headers.so 행의 주석 처리가 제거되었는지 확인하기 만하면됩니다.
Mike Kormendy

내 원산지에는 포트 번호가 있으므로 다음과 같이 정규 표현식을 수정했습니다. ^http(s)?://(.+\.)?example\.com(:\d+)?$
indiv

5

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

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

3

보다 유연한 접근 방식은 Apache 2.4의 표현식을 사용하는 것입니다. 도메인, 경로 및 기타 모든 요청 변수와 일치시킬 수 있습니다. 전송 된 응답은 항상 *이지만, 요청을받는 유일한 요청자는 어쨌든 요구 사항을 충족하는 요청자입니다. 사용 Origin(또는 다른) 표현의 요청 헤더가 자동으로 병합 아파치 인해 Vary해당 응답이 다른 기원 재사용되지 않도록, 응답 헤더.

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

2
일부 브라우저는 *로그인과 같은 자격 증명을 허용하지 않기 때문에 여기에 왔습니다 . 따라서 대신 일치하는 호스트 이름을 전달하는 것이 좋습니다 *.
KeitelDOG

@KeitelDOG 각 도메인에 대해 코드를 반복하는 대신 여러 출처가있는 경우 올바른 출처를 동적으로 캡처하여 다시 보내는 방법은 무엇입니까? 그것은 것 같습니다 수있는 표현으로 가능하지만 문서 나에게 취소되지 않습니다.
Walf

사실 내 진짜 문제는 laravel이 서버 가이 출처를 허용하는지 확인하기 위해 헤더를 검사하는 프리 플라이트 요청에 대해 Access-Control-Allow-Origin헤더를 반환하지 않았기 때문 OPTIONS입니다. 나는 그것을 고쳤다. 그래서는 *나를 위해 진짜 문제가 아니었다. 그러나 여전히 일부 브라우저는 *자격 증명을 허용하지 않으므로 웹 응용 프로그램이 Cross-Origin 요청을 보낼 때 Apache 또는 PHP에서 HTTP_ORIGIN변수 Origin로 동적으로 액세스 할 수있는 헤더를 지정 해야합니다 . 어쨌든 귀하의 솔루션은 모든 출처를 허용하지만 덜 안전합니다.htaccess$_SERVER['HTTP_ORIGIN'];
KeitelDOG

그러나 기억해야 할 것은 1) 제공 *하면 모든 것이 가능 하다는 것입니다. 2) HOST는 ORIGIN과 다릅니다. HOST는 요청 헤더로 전달되는 실제 'TARGET HOST'입니다. 그러나 ORIGIN은에 INITIAL HOST요청을 보내는 것 TARGET HOST입니다. 따라서 코드에서 ORIGIN HOST무시되고 사용되지 않습니다. 위의 답변을 참조하면 ORIGIN값을 사용하여 값을 추가 하는 방법을 볼 수 있습니다 Access-Control-Allow-Origin.
KeitelDOG

@KeitelDOG 표현식에서 요청 헤더를 *사용하면 Origin요청 헤더를 Vary사용하지 않는 한 Apache가 자동으로 응답 헤더에 요청 헤더를 병합 하므로 모든 사람을 허용하지 않습니다 req_novary('Origin'). 브라우저는 다른 응답에 대해 다른 응답을 얻을 수 있으며 Origin보낸 값이 테스트를 통과하지 못하면 Access-Control-Allow-Origin헤더가 설정되지 않습니다.
Walf

2

일부 브라우저에서는 HTTP_ORIGIN을 사용하지 않습니다. HTTP_ORIGIN은 얼마나 안전합니까? 나를 위해 FF에서 비어 있습니다.
내 사이트에 대한 액세스를 허용하는 사이트가 사이트 ID를 통해 전송 된 후 DB에서 해당 ID의 레코드를 확인하고 SITE_URL 열 값 (www.yoursite.com)을 얻습니다.

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

유효한 사이트 ID를 통해 전송하더라도 요청은 해당 사이트 ID와 연결된 내 DB에 나열된 도메인에서 가져와야합니다.


2

다음은 최신 및 계획된 글꼴 정의가 포함 된 아파치에 대한 확장 된 옵션입니다.

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

2

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

이것은 OPTIONS동사의 CORS 처리 도 가능합니다.


2

하위 도메인 일치를위한 PHP 코드 예제.

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

2

.NET 응용 프로그램의 복사 / 붙여 넣기를 쉽게하기 위해 global.asax파일 내에서 CORS를 사용하도록 작성했습니다 . 이 코드는 현재 승인 된 답변에 제공된 조언을 따르며 요청에 응답이 제공된 모든 출처를 반영합니다. 이를 사용하지 않고 '*'를 효과적으로 달성합니다.

그 이유 는 'withCredentials'속성이 'true'로 설정된 AJAX XMLHttpRequest를 보내는 기능을 포함하여 여러 다른 CORS 기능을 사용할 수 있기 때문입니다 .

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

2

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');

1

그리고 장고에서 한 가지 더 대답합니다. 단일 뷰로 여러 도메인의 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

AWS Lambda / API 게이트웨이

서버리스 AWS Lambda 및 API 게이트웨이에서 여러 출처를 구성하는 방법에 대한 자세한 내용은 상당히 간단한 솔루션이지만 상당히 간단해야합니다. 여기를 참조하십시오.

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 게이트웨이 측에서이를 수행하는 것이 좋습니다 (위의 두 번째 링크 참조).


2
Access-Control-Allow-Credentials: true와일드 카드와 함께 사용할 수 없습니다 Access-Control-Allow-Origin: *. <origin>대신 구체적으로 설정하십시오 .

@Tom, 그래, 왜 거기에 있는지 잘 모르겠지만, 기억할 수 없지만 AWS에 추가 된 기본값에서 복사했을 수 있습니까? 지적 해 주셔서 감사합니다.
timhc22

0

SSL을 통한 광고 게재RFC 자체문법에 대한 Google의 답변 은 URL을 공백으로 구분할 수 있음을 나타내는 것 같습니다. 다른 브라우저에서 이것이 얼마나 잘 지원되는지 확실하지 않습니다.


'ssl을 통한 광고 게재'는 사양 w3.org/TR/cors/#access-control-allow-origin-response-header로 연결되어 "실제로 원산지 목록 또는 널 (null) 생산이 더 제한됩니다. 공백으로 구분 된 원점 목록을 허용하는 대신 단일 원점 또는 문자열 "null"
spazm

세부 사항에 주목하는 것이 중요하지만, 사양이 "실제"라고한다고해서 그렇게하는 것이 유효하다는 의미는 아닙니다. 즉, 대부분의 구현자가 스펙을 잘못 또는 불완전하게 구현하므로 문제가 발생할 수 있습니다. 이 사양은 공백으로 구분 된 원점 목록을 허용합니다 origin-list. 여기는
Bob Aman

0

CORS를 사용하여 작동하게하기 위해 나와 같은 많은 코드 예제를 시도하는 경우 실제로 작동하는지 먼저 캐시를 지우고 오래된 이미지가 여전히 존재하는 경우와 같은 문제와 비슷하다는 점을 언급해야합니다. 서버에서 삭제되었으므로 여전히 캐시에 저장되기 때문입니다.

예를 들어 CTRL + SHIFT + DELChrome에서 캐시를 삭제합니다.

이것은 많은 순수한 .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

아래 답변은 C #에만 해당되지만이 개념은 모든 다른 플랫폼에 적용 가능해야합니다.

웹 API에서 교차 출처 요청을 허용하려면 애플리케이션에 옵션 요청을 허용하고 컨트롤러 레벨에서 아래 주석을 추가해야합니다.

[EnableCors (UrlString, Header, Method)] 이제 원점은 문자열로만 전달 될 수 있습니다. 따라서 요청에서 둘 이상의 URL을 전달하려면 쉼표로 구분 된 값으로 전달하십시오.

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


0

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
  }

-2

또한 Asp.net 응용 프로그램의 Global.asax 파일에서이를 설정할 수 있습니다.

protected void Application_BeginRequest(object sender, EventArgs e)
    {

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

    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.