CORS 프리 플라이트 캐시를 전체 도메인에 적용하는 방법


78

CORS를 사용하는 REST 애플리케이션을 구축 중입니다. 모든 REST 호출은 다르며 preflight OPTIONS 호출을받는 데 상당한 오버 헤드가 있음을 발견했습니다. 동일한 도메인에 대한 후속 호출이 캐시 된 응답을 사용하도록 프리 플라이트 OPTIONS 결과를 캐시하고 적용하는 방법이 있습니까?


1
질문에 대한 부록 : 더 작은 범위에 대한 프리 플라이트 캐싱이 불가능한 경우 RESTful 애플리케이션에서 프리 플라이트 요청 수를 제한하는 가장 좋은 방법은 무엇입니까?
Rob W

1
역방향 프록시 인 nginx를 확인하면 CORS 비행 전 페널티를 피할 수 있습니다. 간단히 / API를 매핑 -> api.site.com
더글러스 퍼거슨

CORSWikipedia 기사 에는 프리 플라이트 호출이 수행되는 조건 (및이를 방지하는 방법)을 이해하는 데 도움이되는 멋진 흐름도가 있습니다.
Trenton

답변:


104

프리 플라이트는 전체 도메인이 아닌 요청에만 적용 할 수 있습니다. 같은 질문을 메일 링리스트에 올렸는데 보안 문제가있었습니다. 다음은 전체 스레드입니다. http://lists.w3.org/Archives/Public/public-webapps/2012AprJun/0228.html

실행 전 요청 수를 제한하려면 몇 가지 고려할 사항이 있습니다. 먼저 WebKit / Blink 기반 브라우저는 최대 프리 플라이트 캐시를 10 분으로 설정합니다.

https://github.com/WebKit/webkit/blob/master/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp https://chromium.googlesource.com/chromium/blink/+/master/Source/core/loader/CrossOriginPreflightResultCache .cpp

(다른 브라우저에서도 이것이 사실인지 확실하지 않습니다). 따라서 항상 Access-Control-Max-Age 헤더를 설정해야하지만 최대 값은 10 분입니다.

다음으로 PUT / DELETE 요청에 대한 프리 플라이트를 피하는 것은 불가능합니다. 따라서 API를 업데이트 / 삭제하려면 10 분마다 최소 한 번의 프리 플라이트가 필요합니다.

GET / POST에서 가능한 경우 사용자 지정 헤더를 사용하지 마십시오. 이러한 헤더는 여전히 프리 플라이트를 트리거하기 때문입니다. API가 JSON을 반환하는 경우 'application / json'의 Content-Type도 프리 플라이트를 트리거합니다.

API가 얼마나 "휴식"인지 기꺼이 구부리고 싶다면 몇 가지 더 시도해 볼 수 있습니다. 하나는 'text / plain'과 같이 프리 플라이트가 필요없는 Content-Type을 사용하는 것입니다. 사용자 지정 헤더는 항상 프리 플라이트를 트리거하므로 사용자 지정 헤더가있는 경우 쿼리 매개 변수로 이동할 수 있습니다. 극단적 인 경우 모든 요청이 단일 엔드 포인트로 이루어지는 JSON-RPC와 같은 프로토콜을 사용할 수 있습니다.

솔직히 말해서 브라우저의 프리 플라이트 캐시 제한 10 분과 REST의 리소스 URL 때문에 프리 플라이트 캐시는 상당히 쓸모가 없습니다. 장기간 실행되는 앱 과정에서 프리 플라이트를 제한하기 위해 할 수있는 일은 거의 없습니다. CORS 사양의 작성자가 앞으로이 문제를 해결하기를 바랍니다.


3
@uglymunky 나는 그 섹션을 명확히 할 것이다. 프리 플라이트 캐시의 키는 원본 / URL 쌍을 기반으로하며, 여기서 URL은 전체 요청 URL입니다. 내가 의미하는 것은 사용자 지정 헤더가 있으면 GET 요청에서도 항상 프리 플라이트를 트리거한다는 것입니다. 그러나 사용자 지정 헤더를 쿼리 매개 변수로 이동하면 GET / POST 요청에 대한 프리 플라이트가 없습니다.
monsur jul.

2
@monsur 안녕하세요. 파티에 조금 늦었지만 조언을 해주실 수 있는지 궁금합니다. 저는 현재 모든 요청과 함께 Authorization 헤더 (예 : "Basic [base64 encoding string]")를 API에 전달하고 있습니다. 실행 전 요청은 주로 앱의 성능을 방해하고 있습니다. 토큰 기반 인증 시스템 (URL에 QS 매개 변수로 토큰 포함)으로 이동하고 사용자 지정 헤더를 완전히 제거한다면 GET 및 POST에 대한 두려운 OPTIONS 요청을 피하는 방법이 될 것입니다. m 괜찮아요 PUT 및 DELETE에 대한 일부가 있습니다)?
adaam

5
@adaam 그 트릭을해야합니다. 동작을 더 잘 이해하기 위해 Firefox 및 Chrome에서 몇 가지 테스트를 완료했으며이를 공유 할 수 있습니다. 사용자 지정 헤더가있는 경우 브라우저는 Access-Control-Max-Age이 존재하고 정확히 동일한 URL이 표시 되지 않는 한 OPTIONS 요청을 트리거합니다. 브라우저가 이전에 지정한 기간 내에 있고 Access-Control-Max-Age문제의 브라우저가 값을 줄이지 않습니다 (Webkit, Firefox). 사용자 지정 헤더를 제거하고 URL로 이동하면 브라우저가 OPTIONS 요청을 보내지 않습니다. 승리!
mikegradek

2
나는 그들이 귀하의 이메일에 대한 응답을 중단 한 방식을 좋아합니다. 단일 엣지 케이스에 대한이 모든 중복 호출.
Rebs

3
귀하의 답변에서 Content-Type 제한은 데이터를 보낼 때가 아니라 데이터를 보낼 때만 관련이 있으므로 서버가 임의의 콘텐츠 유형 헤더를 반환하는 데 문제가 없습니다.
letmaik

6

xDomain을 사용해보십시오

angular 또는 jQuery를 사용하는 경우 설정하는 것이 매우 간단했습니다. 앱 서버에서 아래 링크의 도움말에 명시된대로 proxy.html을 추가하십시오. "클라이언트"와 비올라에 js 파일을 참조하는 태그를 추가하십시오. 더 이상 프리 플라이트가 아닙니다. 이것은 cors 검사가 필요하지 않도록 iframe으로 래핑됩니다.

https://github.com/jpillora/xdomain


1

한 가지 방법은 모든 API 호출을 프런트 엔드와 동일한 도메인으로 지정할 수 있다는 것입니다. API 호출 만 API 서버로 전달하도록 프런트 엔드 서버에 nginx를 설정합니다. 모든 비행 전 통화가 제거됩니다.

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