Programing

Access-Control-Allow-Origin 와일드 카드 하위 도메인, 포트 및 프로토콜

lottogame 2020. 3. 23. 08:01
반응형

Access-Control-Allow-Origin 와일드 카드 하위 도메인, 포트 및 프로토콜


모든 하위 도메인, 포트 및 프로토콜에 CORS를 사용하려고합니다.

예를 들어 http://sub.mywebsite.com:8080/ 에서 https://www.mywebsite.com/으로 XHR 요청을 실행할 수 있기를 원합니다. *

일반적으로 원점 일치 요청을 활성화하고 싶습니다 (및 제한).

//*.mywebsite.com:*/*


DaveRandom의 답변을 바탕으로 , 나는 또한 Access-Control-Allow-Origin재 작성 규칙을 사용하지 않고 동일한 결과 ( 현재 특정 프로토콜 + 도메인 + 포트로 동적으로 설정 됨)를 생성하는 약간 더 간단한 Apache 솔루션을 발견했습니다 .

SetEnvIf Origin ^(https?://.+\.mywebsite\.com(?::\d{1,5})?)$   CORS_ALLOW_ORIGIN=$1
Header append Access-Control-Allow-Origin  %{CORS_ALLOW_ORIGIN}e   env=CORS_ALLOW_ORIGIN
Header merge  Vary "Origin"

그리고 그게 다야.

모든 하위 도메인 외에 상위 도메인 (예 : mywebsite.com)에서 CORS를 활성화하려는 사용자는 첫 번째 줄의 정규 표현식을 다음과 같이 간단히 바꿀 수 있습니다.

^(https?://(?:.+\.)?mywebsite\.com(?::\d{1,5})?)$.

참고 : 사양 준수 및 올바른 캐싱 동작을 위해 항상 Vary: OriginCORS가 아닌 리소스 및 비 CORS 요청 및 허용되지 않은 오리진의 요청에 대한 응답 헤더를 추가 하십시오 ( 예제 참조 ).


CORS 사양은 전부 또는 아무것도 아닙니다. 그것은 단지 지원 *, null또는 정확한 프로토콜 + 도메인 + 포트 : http://www.w3.org/TR/cors/#access-control-allow-origin-response-header

서버는 정규식을 사용하여 오리진 헤더의 유효성을 검사해야하며 Access-Control-Allow-Origin 응답 헤더에서 오리진 값을 에코 할 수 있습니다.


편집 : 이 대신 @Noyo의 솔루션을 사용하십시오 . 로드시 더 단순하고 명확하며 성능이 훨씬 뛰어납니다.

역사적 목적만을위한 오리지널 답변 왼쪽.


나는이 문제를 해결하고 Apache와 작동하는 재사용 가능한 .htaccess (또는 httpd.conf) 솔루션을 생각해 냈습니다.

<IfModule mod_rewrite.c>
<IfModule mod_headers.c>
    # Define the root domain that is allowed
    SetEnvIf Origin .+ ACCESS_CONTROL_ROOT=yourdomain.com

    # Check that the Origin: matches the defined root domain and capture it in
    # an environment var if it does
    RewriteEngine On
    RewriteCond %{ENV:ACCESS_CONTROL_ROOT} !=""
    RewriteCond %{ENV:ACCESS_CONTROL_ORIGIN} =""
    RewriteCond %{ENV:ACCESS_CONTROL_ROOT}&%{HTTP:Origin} ^([^&]+)&(https?://(?:.+?\.)?\1(?::\d{1,5})?)$
    RewriteRule .* - [E=ACCESS_CONTROL_ORIGIN:%2]

    # Set the response header to the captured value if there was a match
    Header set Access-Control-Allow-Origin %{ACCESS_CONTROL_ORIGIN}e env=ACCESS_CONTROL_ORIGIN
</IfModule>
</IfModule>

그냥 설정 ACCESS_CONTROL_ROOT루트 도메인에 블록의 상단에 변수를 그리고 그것은 메아리 Origin:에서 클라이언트에 요청 헤더 값 다시 Access-Control-Allow-Origin:는 도메인과 일치하는 경우 응답 헤더 값을.

참고 또한 당신이 사용할 수 sub.mydomain.com는 AS ACCESS_CONTROL_ROOT그것은에 기원을 제한합니다 sub.mydomain.com*.sub.mydomain.com(도메인 루트가 될 필요가 없습니다 그것을 즉). 변경 가능한 요소 (프로토콜, 포트)는 정규식의 URI 일치 부분을 수정하여 제어 할 수 있습니다.


허용 된 답변 은 기본 도메인과 일치 할 수 없으며 하위 도메인에서만 작동하기 때문에이 질문에 대답하고 있습니다. 또한 정규식 그룹화는 성능 적중 이므로 필요하지 않습니다.

예를 들어 http://mywebsite.com에 CORS 헤더를 보내지 않고 http://somedomain.mywebsite.com/에 작동합니다 .

SetEnvIf Origin "http(s)?://(.+\.)?mywebsite\.com(:\d{1,5})?$" CORS=$0

Header set Access-Control-Allow-Origin "%{CORS}e" env=CORS
Header merge  Vary "Origin"

사이트를 활성화하려면 위의 Apache 구성에서 "mywebsite.com"대신 사이트를 배치하면됩니다.

여러 사이트를 허용하려면

SetEnvIf Origin "http(s)?://(.+\.)?(othersite\.com|mywebsite\.com)(:\d{1,5})?$" CORS=$0

배포 후 테스트 :

다음 컬 응답에는 변경 후 "Access-Control-Allow-Origin"헤더가 있어야합니다.

curl -X GET -H "Origin: http://examplesite1.com" --verbose http://examplesite2.com/query

PHP 전용 솔루션이 필요했기 때문에 누군가가 필요로하는 경우를 대비하여. "* .example.com"과 같은 허용 된 입력 문자열을 사용하고 입력이 일치하면 요청 헤더 서버 이름을 반환합니다.

function getCORSHeaderOrigin($allowed, $input)
{
    if ($allowed == '*') {
        return '*';
    }

    $allowed = preg_quote($allowed, '/');

    if (($wildcardPos = strpos($allowed, '*')) !== false) {
        $allowed = str_replace('*', '(.*)', $allowed);
    }

    $regexp = '/^' . $allowed . '$/';

    if (!preg_match($regexp, $input, $matches)) {
        return 'none';
    }

    return $input;
}

다음은 phpunit 데이터 제공자의 테스트 사례입니다.

//    <description>                            <allowed>          <input>                   <expected>
array('Allow Subdomain',                       'www.example.com', 'www.example.com',        'www.example.com'),
array('Disallow wrong Subdomain',              'www.example.com', 'ws.example.com',         'none'),
array('Allow All',                             '*',               'ws.example.com',         '*'),
array('Allow Subdomain Wildcard',              '*.example.com',   'ws.example.com',         'ws.example.com'),
array('Disallow Wrong Subdomain no Wildcard',  '*.example.com',   'example.com',            'none'),
array('Allow Double Subdomain for Wildcard',   '*.example.com',   'a.b.example.com',        'a.b.example.com'),
array('Don\'t fall for incorrect position',    '*.example.com',   'a.example.com.evil.com', 'none'),
array('Allow Subdomain in the middle',         'a.*.example.com', 'a.bc.example.com',       'a.bc.example.com'),
array('Disallow wrong Subdomain',              'a.*.example.com', 'b.bc.example.com',       'none'),
array('Correctly handle dots in allowed',      'example.com',     'exampleXcom',            'none'),

Access-Control-Allow-Origin.htaccess에서 설정하면 다음 작업 만 수행되었습니다.

SetEnvIf Origin "http(s)?://(.+\.)?domain\.com(:\d{1,5})?$" CRS=$0
Header always set Access-Control-Allow-Origin "%{CRS}e" env=CRS

나는 여러 가지 다른 제안 키워드를 시도 Header append, Header set, 아무도 일하지 키워드가 오래된 또는 유효하지 않은 경우 내가 아무 생각이 없지만, SO에 많은 답변에 제안 의 nginx .

내 완전한 해결책은 다음과 같습니다.

SetEnvIf Origin "http(s)?://(.+\.)?domain\.com(:\d{1,5})?$" CRS=$0
Header always set Access-Control-Allow-Origin "%{CRS}e" env=CRS
Header merge Vary "Origin"

Header always set Access-Control-Allow-Methods "GET, POST"
Header always set Access-Control-Allow-Headers: *

# Cached for a day
Header always set Access-Control-Max-Age: 86400

RewriteEngine On

# Respond with 200OK for OPTIONS
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]

"쿠키 도메인"(www.domain.tld)에서 글꼴을 읽을 때 정적 "쿠키가없는"도메인에서 Font Awesome과 비슷한 문제가 발생했으며이 게시물이 우리의 영웅이었습니다. 여기를 참조하십시오 : 어떻게 '누락 간 리소스 공유 (CORS) 응답 헤더'webfont 문제를 해결할 수 있습니까?

copy / paste-r 유형 (및 소품을 제공하기 위해)에 대해서는 모든 기부금에서 이것을 모아서 사이트 루트의 .htaccess 파일 맨 위에 추가했습니다.

<IfModule mod_headers.c>
 <IfModule mod_rewrite.c>
    SetEnvIf Origin "http(s)?://(.+\.)?(othersite\.com|mywebsite\.com)(:\d{1,5})?$" CORS=$0
    Header set Access-Control-Allow-Origin "%{CORS}e" env=CORS
    Header merge  Vary "Origin"
 </IfModule>
</IfModule>

매우 안전하고 우아합니다. 그것을 좋아하십시오 : 당신은 자원 도둑 / 핫 링크 유형의 서버 대역폭을 열 필요가 없습니다.

소품 : @Noyo @DaveRandom @ pratap-koritala

(이 답변을 수락 된 답변에 대한 의견으로 남기려고했지만 아직 그렇게 할 수는 없습니다)


원래 답변은 Apache 2.4 이전의 답변이었습니다. 그것은 나를 위해 작동하지 않았다. 다음은 2.4에서 작동하도록 변경 한 내용입니다. 이것은 yourcompany.com 의 모든 하위 도메인에 적용 됩니다.

SetEnvIf Host ^((?:.+\.)*yourcompany\.com?)$    CORS_ALLOW_ORIGIN=$1
Header append Access-Control-Allow-Origin  %{REQUEST_SCHEME}e://%{CORS_ALLOW_ORIGIN}e    env=CORS_ALLOW_ORIGIN
Header merge  Vary "Origin"

고아 가 정규식으로 끝나서 실제 호스트 (프로토콜 또는 포트에주의를 기울이지 않음) 만 비교 하기 위해 Lars의 답변을 약간 수정 \해야했으며 localhost프로덕션 도메인 이외의 도메인 을 지원하고 싶었습니다 . 따라서 $allowed매개 변수를 배열로 변경했습니다 .

function getCORSHeaderOrigin($allowed, $input)
{
    if ($allowed == '*') {
        return '*';
    }

    if (!is_array($allowed)) {
        $allowed = array($allowed);
    }

    foreach ($allowed as &$value) {
        $value = preg_quote($value, '/');

        if (($wildcardPos = strpos($value, '\*')) !== false) {
            $value = str_replace('\*', '(.*)', $value);
        }
    }

    $regexp = '/^(' . implode('|', $allowed) . ')$/';

    $inputHost = parse_url($input, PHP_URL_HOST);

    if ($inputHost === null || !preg_match($regexp, $inputHost, $matches)) {
        return 'none';
    }

    return $input;
}

다음과 같이 사용법 :

if (isset($_SERVER['HTTP_ORIGIN'])) {
    header("Access-Control-Allow-Origin: " . getCORSHeaderOrigin(array("*.myproduction.com", "localhost"), $_SERVER['HTTP_ORIGIN']));
}

들어 봄 부팅 나는이 발견 RegexCorsConfiguration공식을 확장하는을 CorsConfiguration: https://github.com/looorent/spring-security-jwt/blob/master/src/main/java/be/looorent/security/jwt/RegexCorsConfiguration.java


Lars의 답변이 약간 변경되었습니다.

<?php
function validateOrigin($allowed, $input)
{
    if ($allowed == '*') {
        return '*';
    }

    $allowed = preg_quote($allowed, '/');

    if (($wildcardPos = strpos($allowed, '\*')) !== false) {
        $allowed = str_replace('\*', '(.*)', $allowed);
    }

    $regexp = '/^' . $allowed . '$/';

    if (!preg_match($regexp, $input, $matches)) {
        return 'none';
    }

    return $input;
}

// CORS Preflight
if($_SERVER['REQUEST_METHOD'] === 'OPTIONS')
{
    header('Access-Control-Allow-Origin: '.validateOrigin('https://*.domain.com', $_SERVER['HTTP_ORIGIN']));
    header('X-Response-Code: 204', true, 204);
    header('Access-Control-Allow-Methods: GET');
    header('Access-Control-Allow-Headers: Content-Type');
} elseif($_SERVER['REQUEST_METHOD'] === 'GET'
    && isset($_GET['VARIABLEHERE'])
) {
    // CODE HERE

    if($info["http_code"] === 200){
        // 200 OK
        header('Content-type: application/json; charset=utf-8');
        // CORS headers
        header('Access-Control-Allow-Origin: '.validateOrigin('https://*.domain.com', $_SERVER['HTTP_ORIGIN']));
        echo $response;
    } else {
        header('X-Service-Response-Code: '.$info["http_code"], true, $info["http_code"]);
    }
} else {
    // 400 bad request.
    header('X-Response-Code: 400', true, 400);
}

exit;

참고 URL : https://stackoverflow.com/questions/14003332/access-control-allow-origin-wildcard-subdomains-ports-and-protocols

반응형