답변:
2018-09-13 편집 : 비행 전 요청에 대한 정밀도와 응답이 끝날 때이를 피하는 방법을 추가했습니다.
OPTIONS
요청은 pre-flight
에서 요청 이라고 합니다 Cross-origin resource sharing (CORS)
.
특정 상황에서 다른 출처로 요청을 할 때 필요합니다.
이 비행 전 요청은 일부 브라우저에서 수행되는 요청을 서버에서 신뢰하는지 확인하기위한 안전 조치로 이루어집니다. 서버는 요청시 전송되는 메소드, 오리진 및 헤더가 작동하기에 안전하다는 것을 이해합니다.
교차 요청을 할 때마다 서버는 무시하지 말고 이러한 요청을 처리해야합니다.
http://enable-cors.org/ 에서 좋은 리소스를 찾을 수 있습니다 .
이러한 방법을 편하게 처리 할 수있는 OPTIONS
방법은 메소드가 있는 경로에 대해 서버가이 헤더로 응답을 보내도록하는 것입니다.
Access-Control-Allow-Origin: *
그러면 서버가 서버가 모든 출처의 요청에 응답 할 의사가 있음을 브라우저에 알립니다.
서버에 CORS 지원을 추가하는 방법에 대한 자세한 정보는 다음 플로우 차트를 참조하십시오.
http://www.html5rocks.com/static/images/cors_server_flowchart.png
2018-09-13 수정
CORS OPTIONS
요청은 MDN 문서에 설명 된대로 일부 경우에만 트리거됩니다 .
일부 요청은 CORS 프리 플라이트를 트리거하지 않습니다. Fetch 스펙 (CORS를 정의 함)은이 용어를 사용하지 않지만,이 기사에서는이를 "간단한 요청"이라고합니다. CORS 프리 플라이트를 트리거하지 않는 요청 (소위 "단순 요청")은 다음 조건을 모두 충족하는 요청입니다.
허용되는 유일한 방법은 다음과 같습니다.
- 가져 오기
- 머리
- 게시하다
사용자 에이전트가 자동으로 설정 한 헤더 (예 : Connection, User-Agent 또는 Fetch 사양에 "금지 헤더 이름"으로 정의 된 이름을 가진 다른 헤더) 외에는 다음과 같은 유일한 헤더가 허용됩니다. 수동 설정은 Fetch 사양이 "CORS 안전 요청 헤더"로 정의한 것입니다.
- 동의하기
- 언어를 받아들이십시오
- 내용 언어
- 콘텐츠 유형 (하지만 아래의 추가 요구 사항에 유의)
- DPR
- 다운 링크
- 데이터를 저장
- 뷰포트 폭
- 폭
Content-Type 헤더에 허용되는 유일한 값은 다음과 같습니다.
- application / x-www-form-urlencoded
- 멀티 파트 / 폼 데이터
- 텍스트 / 일반
요청에 사용 된 XMLHttpRequestUpload 객체에는 이벤트 리스너가 등록되어 있지 않습니다. 이들은 XMLHttpRequest.upload 속성을 사용하여 액세스합니다.
요청에 ReadableStream 객체가 사용되지 않습니다.
curl
API에 a 를 사용 하면 어떻게 작동합니까?하지만 크롬에서 실행할 때 오류가 발생합니까?
Origin
요청이 특정 호스트 (예 : yourwebsite.com)에서 온 것처럼 시뮬레이션하기 위해 요청에 헤더를 추가하여 CORS를 시뮬레이션 할 수 있습니다 . 요청의 HTTP 메소드 OPTIONS
와 Access-Control-*
헤더 를 설정하여 프리 플라이트 요청을 시뮬레이션 할 수도 있습니다.
이 문제를 겪은 다음은이 문제에 대한 결론과 해결책입니다.
CORS 전략 에 따르면 (강제로 읽어 보는 것이 좋습니다) 필요한 경우 브라우저가 OPTIONS 요청 전송을 중지하도록 강요 할 수는 없습니다.
이 문제를 해결할 수있는 두 가지 방법이 있습니다.
Access-Control-Max-Age
OPTIONS 요청으로 설정간단한 사이트 간 요청은 다음 조건을 모두 충족하는 요청입니다.
허용되는 유일한 방법은 다음과 같습니다.
사용자 에이전트가 자동으로 설정 한 헤더 (예 : Connection, User-Agent 등) 외에 수동으로 설정할 수있는 유일한 헤더는 다음과 같습니다.
Content-Type 헤더에 허용되는 유일한 값은 다음과 같습니다.
간단한 요청으로 비행 전 OPTIONS 요청이 발생하지 않습니다.
Access-Control-Max-Age
OPTIONS 요청에 대해 를 설정하여 만료 될 때까지 권한을 다시 확인하지 않도록 할 수 있습니다.
Access-Control-Max-Age는 다른 프리 플라이트 요청을 보내지 않고 프리 플라이트 요청에 대한 응답을 캐시 할 수있는 시간을 초 단위로 제공합니다.
Access-Control-Max-Age
IS 600
에 따라 10 분, 크롬 소스 코드Access-Control-Max-Age
예를 들어 GET
URL 경로가 동일한 요청이지만 쿼리마다 다른 리소스는 다른 리소스로 취급됩니다. 따라서 두 번째 자원에 대한 요청은 여전히 프리 플라이트 요청을 트리거합니다.Access-Control-Max-Age
. 이것이 핵심입니다. 과도한 비행 전 요청을 피하는 데 도움이됩니다.
application/json
요청을 "단순"하게하므로 CORS를 트리거하기 때문에 피하지 마십시오 . 브라우저가 작업을 수행하고 있습니다. 서버가 헤더와 같은 것을 반환하도록 설정 Access-Control-Max-Age: 86400
하면 브라우저가 24 시간 동안 OPTIONS 요청을 다시 보내지 않습니다.
사전 비행 옵션 요청의 실제 필요성에 대해서는이 답변을 참조하십시오. CORS- 사전 비행 요청을 도입 한 동기는 무엇입니까?
OPTIONS 요청을 비활성화하려면 ajax 요청에 대해 다음 조건이 충족되어야합니다.
application/x-www-form-urlencoded
, multipart/form-data
또는text/plain
참조 : https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
application/xml
또는 application/json
"사용자 정의 HTTP 헤더"가 아닙니다. 헤더 자체는 Content-Type
해당 헤더를 "custom"이라고 부르는 것이 오해의 소지가 있습니다.
디버그 콘솔을 열고 Disable Cache
옵션을 켜면 프리 플라이트 요청이 항상 전송됩니다 (즉, 각 요청 전에). 캐시를 비활성화하지 않으면 프리 플라이트 요청이 서버 당 한 번만 전송됩니다.
예, 옵션 요청을 피할 수 있습니다. 옵션 요청은 데이터를 다른 도메인으로 보내거나 게시 할 때 프리 플라이트 요청입니다. 브라우저 보안 문제입니다. 그러나 다른 기술인 iframe 전송 계층을 사용할 수 있습니다. CORS 구성을 잊어 버리고 기성품 솔루션을 사용하는 것이 좋습니다. 어디에서나 작동합니다.
https://github.com/jpillora/xdomain을 살펴보십시오.
작업 예제 : http://jpillora.com/xdomain/
존재 이유를 이해하지만 인증없이 OPTIONS 호출을 처리하지 않는 API에 액세스해야하는 개발자의 경우 API 소유자가 적절한 SPA CORS 지원을 추가하거나 프록시 API를받을 때까지 로컬로 개발할 수 있도록 임시 답변이 필요합니다. 가동.
Mac의 Safari 및 Chrome에서 CORS를 비활성화 할 수 있다는 것을 알았습니다.
Chrome : Chrome을 종료하고 터미널을 열고 다음 명령을 붙여 넣습니다. open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir
Safari : Safari에서 동일한 출처 정책 비활성화
Safari에서 동일한 출처 정책을 비활성화하려면 (9.1.1이 있음) 개발자 메뉴 만 활성화하고 개발 메뉴에서 "교차 원본 제한 비활성화"를 선택하면됩니다.
이전 게시물에서 이미 언급했듯이 OPTIONS
요청은 이유가 있습니다. 서버의 응답 시간이 큰 문제 (예 : 해외 연결)가있는 경우 브라우저가 프리 플라이트 요청을 캐시하도록 할 수도 있습니다.
서버가 Access-Control-Max-Age
헤더로 응답 하고 동일한 엔드 포인트로가는 요청에 대해 프리 플라이트 요청이 캐시되어 더 이상 발생하지 않습니다.
OPTIONS
내가 읽은 모든 CORS 문서에서 요청 이이 헤더와 함께 캐시 된다는 사실 은 매우 불투명합니다.
나는이 문제를 좋아했다.
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && ENV == 'devel') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With');
header("HTTP/1.1 200 OK");
die();
}
개발만을위한 것입니다. 이것으로 나는 9ms와 500ms를 기다리고 있지만 8s와 500ms는 아닙니다. 프로덕션 JS 앱은 프로덕션과 동일한 시스템에 있으므로 OPTIONS
개발은 로컬이 아니기 때문에 그렇게 할 수 있습니다 .
JSONP를 사용하여 CORS를 피할 수는 없습니다.
하루 종일 동안 비슷한 문제를 해결하려고 노력한 후 IIS 와 관련이 있음을 알았습니다. .
내 웹 API 프로젝트는 다음과 같이 설정되었습니다.
// WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
//...
}
많은 게시물에서 보았던 것처럼 web.config> system.webServer 노드에 CORS 특정 구성 옵션이 없었습니다.
global.asax 또는 컨트롤러에 데코레이터로 CORS 특정 코드가 없습니다.
문제는 앱 풀 설정 이었습니다.
관리되는 파이프 라인 모드가 클래식 (로 설정되어 통합으로 변경 )과 ID가 네트워크 서비스로 설정 ( ApplicationPoolIdentity로 변경 )
해당 설정을 변경하고 (앱 풀을 새로 고침) 설정이 해결되었습니다.
나를 위해 일한 것은 "github.com/gorilla/handlers"를 가져온 다음 다음과 같이 사용하는 것입니다.
router := mux.NewRouter()
router.HandleFunc("/config", getConfig).Methods("GET")
router.HandleFunc("/config/emcServer", createEmcServers).Methods("POST")
headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type"})
originsOk := handlers.AllowedOrigins([]string{"*"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
log.Fatal(http.ListenAndServe(":" + webServicePort, handlers.CORS(originsOk, headersOk, methodsOk)(router)))
Ajax POST 요청을 실행하고 JSON 데이터를 첨부하자마자 Chrome은 항상 이전 AllowedHeaders 구성에없는 Content-Type 헤더를 추가합니다.
과거에 사용한 한 가지 솔루션-사이트가 mydomain.com에 있다고 가정하고 foreigndomain.com에 아약스 요청을해야합니다.
도메인에서 외부 도메인으로 IIS 다시 쓰기 구성
<rewrite>
<rules>
<rule name="ForeignRewrite" stopProcessing="true">
<match url="^api/v1/(.*)$" />
<action type="Rewrite" url="https://foreigndomain.com/{R:1}" />
</rule>
</rules>
</rewrite>
mydomain.com 사이트에서 동일한 출발지 요청을 할 수 있으며 옵션 요청이 필요 없습니다. :)
요청을 가로 채고 적절한 헤더를 작성하는 프록시를 사용하는 경우 해결할 수 있습니다. 니스의 특별한 경우에는 다음과 같은 규칙이 있습니다.
if (req.http.host == "CUSTOM_URL" ) {
set resp.http.Access-Control-Allow-Origin = "*";
if (req.method == "OPTIONS") {
set resp.http.Access-Control-Max-Age = "1728000";
set resp.http.Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, PATCH, OPTIONS";
set resp.http.Access-Control-Allow-Headers = "Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since";
set resp.http.Content-Length = "0";
set resp.http.Content-Type = "text/plain charset=UTF-8";
set resp.status = 204;
}
}
해결책이있을 수 있습니다 (그러나 테스트하지는 않았습니다) .CSP (Content Security Policy)를 사용하여 원격 도메인을 활성화 할 수 있으며 브라우저는 CORS OPTIONS 요청 확인을 건너 뛸 수 있습니다.
시간이 있으면 테스트 하고이 게시물을 업데이트합니다!
CSP : https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Content-Security-Policy
CSP 사양 : https://www.w3.org/TR/CSP/