OPTIONS 프리 플라이트 요청을 건너 뛰는 방법은 무엇입니까?


93

나는 현재 모바일 웹 사이트로 변환되는 PhoneGap 앱을 개발했습니다. 작은 결함 하나 외에 모든 것이 원활하게 작동합니다. 앱에서는 제대로 작동하지만 모바일 웹 사이트 버전에서는 실패하는 POST 요청을 통해 특정 타사 API를 사용합니다.

자세히 살펴보면 AngularJS (실제로 브라우저가 추측)가 먼저 OPTIONS 요청을 보내는 것처럼 보입니다. 오늘 CORS에 대해 많이 배웠지 만 완전히 비활성화하는 방법을 알아낼 수없는 것 같습니다. 해당 API에 대한 액세스 권한이 없지만 (따라서 해당 측면에서 변경할 수 없음) 작업중인 도메인을 Access-Control-Allow-Origin 헤더에 추가했습니다.

이것이 내가 말하는 코드입니다.

        var request = {
                language: 'fr',
                barcodes: [
                    {
                        barcode: 'somebarcode',
                        description: 'Description goes here'
                    }
                ]
            };
        }
        var config = {
            headers: { 
                'Cache-Control': 'no-cache',
                'Content-Type': 'application/json'
            }
        };
        $http.post('http://somedomain.be/trackinginfo', request, config).success(function(data, status) {
            callback(undefined, data);
        }).error(function(data, status) {
            var err = new Error('Error message');
            err.status = status;
            callback(err);
        });

브라우저 (또는 AngularJS)가 OPTIONS 요청을 보내는 것을 막고 실제 POST 요청으로 건너 뛰려면 어떻게해야합니까? AngularJS 1.2.0을 사용하고 있습니다.

미리 감사드립니다.

답변:


100

프리 플라이트는 Content-Type의 application/json. 이를 방지하는 가장 간단한 방법은 Content-Type을 text/plain귀하의 경우 로 설정하는 것 입니다. application/x-www-form-urlencoded& multipart/form-dataContent-Types도 허용되지만 물론 요청 페이로드의 형식을 적절하게 지정해야합니다.

이 변경 후에도 여전히 프리 플라이트가 표시되는 경우 Angular가 요청에 X- 헤더를 추가 할 수도 있습니다.

또는 트리거 할 헤더 (Authorization, Cache-Control ...)가있을 수 있습니다. 다음을 참조하세요.


9
이것이 정답입니다. Content-Type 및 Cache-Control 헤더가 프리 플라이트 요청을 트리거합니다. Content-Type이 text / plain 인 일반 GET 및 기타 몇 가지가 프리 플라이트되지 않은 요청을 트리거하는 유일한 방법입니다. 참조 : developer.mozilla.org/en-US/docs/HTTP/…
Jeff Hubbard 2014

아 예, Cache-Control은 잊어 버렸습니다.
Ray Nicholus 2014

17
사용자 지정 헤더도 프리 플라이트를 트리거합니다.
Sébastien Deprez

2
OPTIONs 테스트를 방지하기 위해 콘텐츠 유형을 변경하는 것은 답이 아닙니다. 콘텐츠 유형은 관계없이 콘텐츠 유형과 일치해야합니다
ekerner

브라우저가 던지고 백엔드에서 Http 메소드 OPTIONS가 차단되면 브라우저가 OPTIONS 실패로 POST / PUT에 해당하는 API를 호출하지 않는 것과 같은 효과가 있습니까?
P Satish Patro

16

Ray가 말했듯이 콘텐츠 헤더를 다음과 같이 수정하여 중지 할 수 있습니다.

 $http.defaults.headers.post["Content-Type"] = "text/plain";

예를 들어-

angular.module('myApp').factory('User', ['$resource','$http',
    function($resource,$http){
        $http.defaults.headers.post["Content-Type"] = "text/plain";
        return $resource(API_ENGINE_URL+'user/:userId', {}, {
            query: {method:'GET', params:{userId:'users'}, isArray:true},
            getLoggedIn:{method:'GET'}
        });
    }]);

또는 전화로 직접-

var req = {
 method: 'POST',
 url: 'http://example.com',
 headers: {
   'Content-Type': 'text/plain'
 },
 data: { test: 'test' }
}

$http(req).then(function(){...}, function(){...});

이것은 비행 전 옵션 요청을 보내지 않습니다.

참고 : 요청에는 사용자 지정 헤더 매개 변수가 없어야합니다. 요청 헤더에 사용자 지정 헤더가 포함되어 있으면 브라우저가 사전 요청을 수행하므로 피할 수 없습니다.


1
어떻게해야 $http합니까?
learnercys

고마워요, 제가했던 것과 비슷 해요. 유일한 변경 사항은 메서드 GET와 추가 헤더 Authorization입니다. 하지만 여전히 프리 플라이트를 보내고 있습니다.
learnercys

1
여기에 요청을 붙여 넣을 수 있습니까? 컬이나 뭔가? 아마도 Authorization 헤더 때문일 수 있습니다. 제거하고 시도하십시오. 커스텀 헤더를 보내는 경우 angular는 비행 전 요청을 보냅니다.
vivex

pastebin.com/vRDeFiH2 처음에 요청입니다 $ HTTP와 두 번째 : 우편 배달부에 의해 유효한 요청 빌드를하다
learnercys

2

특정 유형의 교차 도메인 AJAX 요청을 수행 할 때 CORS를 지원하는 최신 브라우저는 추가 "프리 플라이트"요청을 삽입하여 작업을 수행 할 권한이 있는지 확인합니다. 예제 쿼리에서 :

$http.get( ‘https://example.com/api/v1/users/’ +userId,
  {params:{
           apiKey:’34d1e55e4b02e56a67b0b66’
          }
  } 
);

이 조각의 결과로 주소에 두 개의 요청 (OPTIONS 및 GET)이 전송되었음을 알 수 있습니다. 서버의 응답에는 쿼리 GET의 허용 여부를 확인하는 헤더가 포함됩니다. 서버가 OPTIONS 요청을 제대로 처리하도록 구성되지 않은 경우 클라이언트 요청이 실패합니다. 예를 들면 :

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept, origin, x-requested-with, content-type
Access-Control-Allow-Methods: DELETE
Access-Control-Allow-Methods: OPTIONS
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Methods: GET
Access-Control-Allow-Methods: POST
Access-Control-Allow-Orgin: *
Access-Control-Max-Age: 172800
Allow: PUT
Allow: OPTIONS
Allow: POST
Allow: DELETE
Allow: GET

2

가장 좋은 방법은 요청이 "OPTIONS"유형인지 확인하여 미들웨어에서 200을 반환하는 것입니다. 그것은 나를 위해 일했습니다.

express.use('*',(req,res,next) =>{
      if (req.method == "OPTIONS") {
        res.status(200);
        res.send();
      }else{
        next();
      }
    });

작동하지만 OWASP에서는 OPTIONS를 노출하지 않는 것이 좋습니다. 백엔드 / 호스팅 서비스 (Nginx, Apache) 등에서 날씨를 차단합니다.
P Satish Patro

0

프리 플라이트는 브라우저에서 구현 된 웹 보안 기능입니다. Chrome의 경우 --disable-web-security 플래그를 추가하여 모든 웹 보안을 비활성화 할 수 있습니다.

예 : "C : \ Program Files \ Google \ Chrome \ Application \ chrome.exe"--disable-web-security --user-data-dir = "C : \ newChromeSettingsWithoutSecurity". 먼저 크롬의 새 바로 가기를 만들고 속성으로 이동하여 위와 같이 대상을 변경할 수 있습니다. 이것이 도움이 될 것입니다!


OP가 클라이언트에게 기능을 활성화하기 위해 브라우저 보안을 해제하라고 말할 수는 없습니다.
svarog

@svarog 이것은 대부분 개발 목적으로 주로 프로덕션 서버 에서이 문제에 직면하지 않습니다.
Arijit Patra

브라우저가 던지고 백엔드에서 Http 메소드 OPTIONS가 차단되면 브라우저가 OPTIONS 실패로 POST / PUT에 해당하는 API를 호출하지 않는 것과 같은 효과가 있습니까?
P Satish Patro

-2

content-type을 undefined로 설정하면 javascript가 헤더 데이터를 그대로 전달하고 기본 각도 $ httpProvider 헤더 구성을 덮어 씁니다. Angular $ http 문서

$http({url:url,method:"POST", headers:{'Content-Type':undefined}).then(success,failure);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.