Access-Control-Allow-Origin을 우회하는 방법?


196

나는 그들이 아약스 호출을 방지하도록 설정된 플랫폼에서 내 서버에 대한 아약스 호출을하고 있습니다 (그러나 서버의 데이터를 가져 와서 서버의 데이터베이스에서 검색 된 데이터를 표시해야합니다). 내 아약스 스크립트가 작동하면 데이터를 서버의 PHP 스크립트로 보내서 처리 할 수 ​​있습니다. 그러나 처리 된 데이터는 다음에 의해 차단되어 다시 가져올 수 없습니다"Access-Control-Allow-Origin"

해당 플랫폼의 소스 / 코어에 액세스 할 수 없습니다. 그래서 내가 할 수없는 스크립트를 제거 할 수 없습니다. (P / SI는 Chrome 콘솔을 사용하여이 오류를 발견했습니다)

아래와 같이 Ajax 코드 :

 $.ajax({
     type: "GET",
     url: "http://example.com/retrieve.php",
     data: "id=" + id + "&url=" + url,
     dataType: 'json',   
     cache: false,
     success: function(data)
      {
        var friend = data[1];              
        var blog = data[2];           
        $('#user').html("<b>Friends: </b>"+friend+"<b><br> Blogs: </b>"+blog);

      } 
  });

또는 JSON위의 ajax 스크립트와 동등한 코드가 있습니까? 나는 JSON허용된다고 생각한다 .

누군가 나를 도울 수 있기를 바랍니다.


지금까지 귀하의 질문에 대한 모든 답변은 서버 코드를 다시 작성하여 아약스가 작동하는 방법을 설명했습니다. 귀하의 질문에 구체적으로 요청한 것처럼 우회에 관한 것은 없습니다. 어쨌든이 헤더를 실제로 우회 할 방법을 찾았습니까? 나는 하나가 있을지 정말로 의심한다.
Moradnejad

베이 패스 할 방법이 없습니다. 그러나 요청을 수행하는 파일을 백엔드에 넣을 수 있습니다. 따라서 아약스마다 파일을 자신의 서버에서 호출하면 해당 파일이 retrieve.php에서 데이터를로드하고 자바 스크립트로 다시 보냅니다. 이 경우 차단하는 CORS 규칙이 없습니다.
Jona Paulus

답변:


365

retrieve.php 위에 이것을 넣으십시오 :

header('Access-Control-Allow-Origin: *');  

이렇게하면 CORS 보호 기능이 효과적으로 비활성화되고 사용자가 공격에 노출 될 수 있습니다. 모든 원점 을 허용 해야하는지 확실하지 않은 경우 보다 구체적인 원점으로 고정해야합니다.

header('Access-Control-Allow-Origin: https://www.example.com')

더 나은 이해를 위해 다음 스택 답변을 참조하십시오 Access-Control-Allow-Origin

https://stackoverflow.com/a/10636765/413670


54
오히려 안전하지 않습니다. 하단에서 내 답변을 확인하십시오.
Rob

3
tnx, @RobQuist가 언급 한대로 모든 출처에 대한 액세스를 허용해서는 안되며 그의 답변에서 더 나은 접근 방법을 제공했습니다
Rafay

2
서버에서 액세스 제어를 실제로 '우회'해야했기 때문에이 페이지를 찾았습니다. 여기서 해결책은 아무것도 우회하는 것이 아니라 자신의 서버에서 액세스 제어를 올바르게 구성하는 것입니다. 실제로 누군가가 이것을 우회 해야하는 경우 PHP의 file_get_contents ($ remote_url);을 사용할 수 있습니다. 이 작업을 수행하는 방법은 여러 가지가 있지만 이것이 내가 한 일입니다.
Shawn Whinnery

1
@ShawnWhinnery는 기본적으로 "프록시"의 행위입니다. 제어 할 수없는 다른 웹 사이트에서 데이터를 동적으로로드하려는 경우에 좋은 솔루션입니다.
Rob

1
dotnet core에서 PHP 스크립트를 실행하고 싶었습니다. PHP 스크립트를 다른 URL로 이동했지만 사이트 간 스크립팅 오류가 발생했습니다. PHP 상단에 보여준 코드를 추가하고 완벽하게 작동했습니다. 감사!
raddevus

290

자, *는 와일드 카드이며 모든 도메인에서 크로스 사이트 스크립팅을 허용한다는 것을 모두 알고 있습니까?

Access-Control-Allow-Origin허용 된 모든 사이트에 대해 여러 헤더 를 보내려고 하지만 불행히도 공식적으로 여러 Access-Control-Allow-Origin헤더 를 보내 거나 여러 출처를 넣을 수는 없습니다.

원점을 확인하고 허용 된 경우 해당 원점을 헤더로 다시 보내서이 문제를 해결할 수 있습니다.

$origin = $_SERVER['HTTP_ORIGIN'];
$allowed_domains = [
    'http://mysite1.com',
    'https://www.mysite2.com',
    'http://www.mysite2.com',
];

if (in_array($origin, $allowed_domains)) {
    header('Access-Control-Allow-Origin: ' . $origin);
}

훨씬 안전합니다. 일치하는 항목을 편집하여 정규식 또는 이와 유사한 것을 사용하여 수동 기능으로 변경할 수 있습니다. 적어도 이것은 단지 1 개의 헤더만을 돌려 줄 것이며, 당신은 그 헤더가 요청의 출처임을 확신 할 것입니다. 모든 HTTP 헤더 스푸핑 수 있지만이 헤더는 클라이언트를 보호하기위한 것입니다. 이러한 값으로 자신의 데이터를 보호하지 마십시오. 더 알고 싶다면 CORS와 CSRF에 대해 조금 읽어보십시오.

왜 더 안전한가요?

다른 위치에서 액세스를 허용하면 자신의 신뢰할 수있는 사이트가 세션 하이재킹을 허용합니다. 이미지 Facebook에서는 와일드 카드를 사용할 수 있습니다. 즉, 자신 만의 웹 사이트를 만들어 AJAX 호출 (또는 열린 iframe)을 페이스 북으로 실행할 수 있습니다. 이것은 당신이 당신의 웹 사이트 방문자의 페이스 북의 로그인 정보를 얻을 수 있음을 의미합니다. 더 나쁜 POST것은 웹 사이트를 탐색하는 동안 요청 을 스크립팅 하고 다른 사람의 페이스 북에 데이터를 게시 할 수 있다는 것입니다.

ACAO헤더를 사용할 때 매우 조심하십시오 !


12
목록의 각 항목 앞에 http : //를 넣어야한다고 생각합니다. 적어도 내가 일하고있는 한 사이트에서 했었습니다.
blak3r

2
슬프게도, 이것은 작동하지 않는 것 같습니다. header () 호출마다 하나의 예외 만 제공 될 수 있다고 생각합니다.
lewsid 2016 년

5
@Shanimal & lewsid-> 쉼표로 구분되어 실제로 작동하지 않는 것 같습니다. 참조 : w3.org/TR/cors
Rob

3
도메인 목록을 다루는 경우 관련 답변 : stackoverflow.com/a/1850482/766177
Valentin Despa

13
각 호출 header()이 동일한 유형의 이전 헤더 를 대체 하기 때문에 4 개의 헤더를 추가하는 것은 의미가 없습니다 . 실제로 당신이하고있는 일은 마지막 헤더를 설정하는 것입니다. 수동 항목 의 두 번째 매개 변수를 설정할 수있는 상태 false이전의 헤더를 덮어 쓰지 않도록 할 수 있습니다.
BadHorsie 2016 년

31

경고 , Chrome 및 기타 브라우저는 다른 답변을 따르는 경우 여러 ACAO 헤더가 설정되어 있다고 불평합니다.

오류는 다음과 같습니다 XMLHttpRequest cannot load ____. The 'Access-Control-Allow-Origin' header contains multiple values '____, ____, ____', but only one is allowed. Origin '____' is therefore not allowed access.

이 시도:

$http_origin = $_SERVER['HTTP_ORIGIN'];

$allowed_domains = array(
  'http://domain1.com',
  'http://domain2.com',
);

if (in_array($http_origin, $allowed_domains))
{  
    header("Access-Control-Allow-Origin: $http_origin");
}

6
이것은 내가 게시 한 것보다 훨씬 나은 솔루션입니다.
Rob

7

MVC3 컨트롤러를 호출 할 때이 문제를 해결했습니다. 나는 덧붙였다 :

Response.AddHeader("Access-Control-Allow-Origin", "*"); 

내 앞에

return Json(model, JsonRequestBehavior.AllowGet);

또한 내 아약스 호출에서 Content-type 헤더를 $.ajax허용하지 않는다고 불평했기 때문에 JSON이 Action에 전달되는 것을 알면서 주석 처리했습니다.

희망이 도움이됩니다.


2

를 사용하는 것은 정말 나쁜 생각 *입니다. 사이트 간 스크립팅을 열 수 있습니다. 기본적으로 항상 현재 도메인 설정을 원하고 현재 SSL 설정 범위와 선택적으로 추가 도메인을 원합니다. 또한 모두 하나의 헤더로 전송되기를 원합니다. 다음은 항상 현재 페이지와 동일한 SSL 범위에서 자신의 도메인을 인증하며 선택적으로 추가 도메인을 포함 할 수 있습니다. 브라우저는 여러 액세스 제어 헤더가 전송되는 것에 대해 브라우저가 엉망이되는 것을 피하기 위해 이미 하나를 헤더로 보내고 다른 항목이 이미 보낸 경우 이전 헤더를 덮어 씁니다.

class CorsAccessControl
{
    private $allowed = array();

    /**
     * Always adds your own domain with the current ssl settings.
     */
    public function __construct()
    {
        // Add your own domain, with respect to the current SSL settings.
        $this->allowed[] = 'http'
            . ( ( array_key_exists( 'HTTPS', $_SERVER )
                && $_SERVER['HTTPS'] 
                && strtolower( $_SERVER['HTTPS'] ) !== 'off' ) 
                    ? 's' 
                    : null )
            . '://' . $_SERVER['HTTP_HOST'];
    }

    /**
     * Optionally add additional domains. Each is only added one time.
     */
    public function add($domain)
    {
        if ( !in_array( $domain, $this->allowed )
        {
            $this->allowed[] = $domain;
        }
    /**
     * Send 'em all as one header so no browsers grumble about it.
     */
    public function send()
    {
        $domains = implode( ', ', $this->allowed );
        header( 'Access-Control-Allow-Origin: ' . $domains, true ); // We want to send them all as one shot, so replace should be true here.
    }
}

용법:

$cors = new CorsAccessControl();

// If you are only authorizing your own domain:
$cors->send();

// If you are authorizing multiple domains:
foreach ($domains as $domain)
{
    $cors->add($domain);
}
$cors->send();

당신은 아이디어를 얻습니다.


1

실제로 서버에서 보낸 응답에 Access-Control-Allow-Origin 헤더를 추가해 보셨습니까? 처럼 Access-Control-Allow-Origin: *?


1
스크립트의 원본 도메인이 서버의 도메인과 일치하지 않더라도 호출 스크립트에 결과를 표시해도 괜찮음을 브라우저에 알리기 위해 서버가 보내는 HTTP 헤더입니다. Cross-Origin Resource Sharing 에 대해 읽어보십시오 !
Daniel Brockman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.