가끔 백그라운드 인터페이스를 호출할 때 아래와 같이 두 번 요청한다는 사실을 눈치채셨는지 모르겠습니다.
사실 우리가 처음 보내는 것은 실행 전 요청( 실행 전 요청), 이 문서에서는 실행 전 요청이 전송되는 이유, 실행 전 요청이 전송되는 시기, 실행 전 요청이 수행하는 작업에 대해 설명합니다
우리 모두는 브라우저의 동일 출처 정책은 보안상의 이유로 브라우저가 스크립트에서 시작된 도메인 간 HTTP 요청을 제한합니다. XMLHttpRequest 및 Fetch는 모두 동일 출처 정책을 따릅니다.
일반적으로 브라우저가 교차 도메인 요청을 제한하는 방법에는 두 가지가 있습니다.
1. 브라우저는 교차 도메인 요청의 시작을 제한합니다.
2. 교차 도메인 요청은 정상적으로 시작될 수 있지만 반환된 결과는 브라우저에 의해 차단됩니다.
OPTIONS
메서드를 사용하여 사전 요청을 시작하여 학습하도록 요구합니다. 서버 정보 교차 도메인 요청을 허용할지 여부: 허용되면 데이터가 포함된 실제 요청을 보냅니다. 그렇지 않으면 데이터가 포함된 실제 요청이 전송되지 않습니다. OPTIONS
方法发起一个预检请求,从而获知服务器是否允许该跨域请求:如果允许,就发送带数据的真实请求;如果不允许,则阻止发送带数据的真实请求。
HTTP请求包括: 简单请求 和 需预检的请求
简单请求不会触发CORS预检请求,“简属于
单请求”术语并不属于Fetch(其中定义了CORS)规范。
若满足所有下述条件,则该请求可视为“简单请求”:
- 使用下列方法之一:
- GET
- HEAD
- POST
- Content-Type
: (仅当POST方法的Content-Type值等于下列之一才算做简单需求)
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
注意: WebKit Nightly 和 Safari Technology Preview 为Accept
, Accept-Language
, 和 Content-Language
首部字段的值添加了额外的限制。如果这些首部字段的值是“非标准”的,WebKit/Safari 就不会将这些请求视为“简单请求”。WebKit/Safari 并没有在文档中列出哪些值是“非标准”的,不过我们可以在这里找到相关讨论:Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language, Allow commas in Accept, Accept-Language, and Content-Language request headers for simple CORS, and Switch to a blacklist model for restricted Accept headers in simple CORS requests。其它浏览器并不支持这些额外的限制,因为它们不属于规范的一部分。
“需预检的请求”要求必须首先使用OPTIONS
方法发起一个预检请求到服务区,以获知服务器是否允许该实际请求。“预检请求”的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。
当请求满足下述任一条件时,即应首先发送预检请求:
- 使用了下面任一 HTTP 方法:
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
- 人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
- Accept
- Accept-Language
- Content-Language
- Content-Type
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-Type
的值不属于下列之一:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
2. 실행 전 요청을 보내는 경우
받기
🎜
- 헤드
🎜
- 포스트
🎜
- Content-Type
: (POST 메소드의 Content-Type 값이 다음 중 하나와 동일한 경우에만 간단한 요구 사항입니다.) 🎜
-
~ ~
- application/x-www-form-urlencoded
🎜🎜참고: WebKit Nightly 및 Safari Technology Preview는 Accept 🎜, Accept-Language 🎜 및 Content-Language입니다. 🎜 헤더 필드 값에 대한 추가 제한 사항을 추가했습니다. 이러한 헤더 필드의 값이 "비표준"인 경우 WebKit/Safari는 이러한 요청을 "단순 요청"으로 처리하지 않습니다. WebKit/Safari는 문서에 어떤 값이 "비표준"인지 나열하지 않지만 여기에서 토론을 찾을 수 있습니다. 비표준 CORS 허용 목록에 있는 요청 헤더 Accept, Accept-Language 및 Content-Language에 대한 사전 비행 필요, 단순 CORS에 대해 Accept, Accept-Language 및 Content-Language 요청 헤더에 쉼표를 허용하고, 단순 CORS 요청에서 제한된 Accept 헤더에 대해 블랙리스트 모델로 전환합니다. 다른 브라우저는 사양에 포함되지 않기 때문에 이러한 추가 제한 사항을 지원하지 않습니다. 🎜
OPTIONS
메서드를 사용하여 서비스 영역에 대한 사전 비행 요청을 시작해야 합니다. 서버가 실제 요청을 허용했는지 여부. "실행 전 요청"을 사용하면 도메인 간 요청이 서버의 사용자 데이터에 예기치 않은 영향을 미치는 것을 방지할 수 있습니다. 🎜🎜요청이 다음 조건 중 하나라도 충족되면 먼저 실행 전 요청을 보내야 합니다. 🎜
- 다음 HTTP 방법 중 하나를 사용합니다: 🎜
- PUT
🎜
- 삭제
🎜
- 연결
🎜
- 옵션
🎜
- TRACE
🎜
- PATCH
🎜- CORS 안전 헤더 필드 세트 이외의 헤더 필드를 인위적으로 설정합니다. 컬렉션은 다음과 같습니다: 🎜
- 수락
🎜
- 수락 언어
🎜
- 콘텐츠 언어
🎜
- 콘텐츠 유형
🎜
- DPR
🎜
- 다운링크
🎜
- 데이터 저장
🎜
- 뷰포트 너비
🎜
- 너비
🎜
- Content-Type
값이 다음 중 하나에 속하지 않습니다. 🎜
- application/x-www-form-urlencoded
🎜
- 다중 부분/양식 데이터
🎜
- 텍스트/일반
🎜다음은 실행 전 요청을 수행해야 하는 HTTP 요청입니다.
var invocation = new XMLHttpRequest(); var url = ' var body = '<?xml version="1.0"?><person><name>Arun</name></person>';function callOtherDomain(){ if(invocation) { invocation.open('POST', url, true); invocation.setRequestHeader('X-PRODUCT', 'H5'); invocation.setRequestHeader('Content-Type', 'application/xml'); invocation.onreadystatechange = handler; invocation.send(body); } } ......
위 코드는 POST 요청을 사용하여 사용자 정의 헤더 필드(X-PRODUCT:H5)가 포함된 XML 문서를 보냅니다. 또한 요청의 Content-Type
은 application/xml
입니다. 따라서 요청은 먼저 "실행 전 요청"을 시작해야 합니다. Content-Type
为application/xml
。因此,该请求需要首先发起“预检请求”。
1. OPTIONS /resources/post-here/ 2. HTTP/1.13. Host: bar.other4. User-Agent: Mozilla/5.0 (Macintosh; U; 5.Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre6. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.87. Accept-Language: en-us,en;q=0.58. Accept-Encoding: gzip,deflate9. Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.710. Connection: keep-alive11. Origin: http://foo.example12. Access-Control-Request-Method: POST13. Access-Control-Request-Headers: X-PINGOTHER, Content-Type14. HTTP/1.1 200 OK15. Date: Mon, 01 Dec 2008 01:15:39 GMT16. Server: Apache/2.0.61 (Unix)17. Access-Control-Allow-Origin: http://foo.example18. Access-Control-Allow-Methods: POST, GET, OPTIONS19. Access-Control-Allow-Headers: X-PINGOTHER, Content-Type20. Access-Control-Max-Age: 8640021. Vary: Accept-Encoding, Origin22. Content-Encoding: gzip23. Content-Length: 024. Keep-Alive: timeout=2, max=10025. Connection: Keep-Alive26. Content-Type: text/plain
从上面的报文中可以看到,第1~12行发送了一个使用OPTIONS
方法的预检请求。 OPTIONS
是HTTP/1.1协议中定义的方法,用以从服务器获取更多信息。该方法不会对服务器资源产生影响。遇见请求中同时携带了下面两个首部字段:
Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PRODUCT
首部字段 Access-Control-Request-Method 告知服务器,实际请求将使用 POST 方法。首部字段 Access-Control-Request-Headers 告知服务器,实际请求将携带两个自定义请求首部字段:X-PINGOTHER 与 Content-Type。服务器据此决定,该实际请求是否被允许。
第14~26行 为预检请求的响应,表明服务器将坚守后续的实际请求。重点看第17~20行:
Access-Control-Allow-Origin: http://foo.exampleAccess-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-TypeAccess-Control-Max-Age: 86400
首部字段 Access-Control-Allow-Methods
表明服务器允许客户端使用 POST,GET 和 OPTIONS 方法发起请求。
首部字段Access-Control-Allow-Headers
表明服务器允许请求中携带字段X-PINGOTHER
与Content-Type
。与 Access-Control-Allow-Methods
一样,Access-Control-Allow-Headers
的值为逗号分割的列表。
最后,首部字段
Access-Control-Max-Age
POST /resources/post-here/ HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3preAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7Connection: keep-aliveX-PINGOTHER: pingpongContent-Type: text/xml; charset=UTF-8Referer: http://foo.example/examples/preflightInvocation.htmlContent-Length: 55Origin: http://foo.examplePragma: no-cacheCache-Control: no-cache<?xml version="1.0"?><person><name>Arun</name></person>HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:40 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://foo.example Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 235 Keep-Alive: timeout=2, max=99 Connection: Keep-Alive Content-Type: text/plain [Some GZIP'd payload]위 메시지에서 볼 수 있듯이 1~12번째 줄은
OPTIONS
메서드를 사용하여 실행 전 요청을 보냅니다. OPTIONS
는 서버로부터 더 많은 정보를 얻기 위해 HTTP/1.1 프로토콜에 정의된 메서드입니다. 이 방법은 서버 리소스에 영향을 주지 않습니다. 요청에는 다음 두 헤더 필드가 동시에 전달됩니다. rrreee
헤더 필드 Access-Control-Request-Method는 실제 요청이 POST 메서드를 사용할 것임을 서버에 알려줍니다. 헤더 필드 Access-Control-Request-Headers는 실제 요청이 두 개의 사용자 정의 요청 헤더 필드인 X-PINGOTHER 및 Content-Type을 전달함을 서버에 알려줍니다. 서버는 이를 기반으로 실제 요청이 허용되는지 여부를 결정합니다. 🎜🎜라인 14~26은 실행 전 요청에 대한 응답으로, 서버가 후속 실제 요청을 고수할 것임을 나타냅니다. 17~20행에 집중하세요. 🎜rrreee🎜헤더 필드Access-Control-Allow-Methods
는 서버가 클라이언트가 POST, GET 및 OPTIONS 메서드를 사용하여 요청을 시작할 수 있도록 허용함을 나타냅니다. 🎜🎜헤더 필드 Access-Control-Allow-Headers
는 서버가 X-PINGOTHER
및 Content-Type
필드의 전달을 허용함을 나타냅니다. 요청에. Access-Control-Allow-Methods
와 마찬가지로 Access-Control-Allow-Headers
값은 쉼표로 구분된 목록입니다. 🎜🎜마지막으로 헤더 필드 🎜🎜Access-Control-Max-Age
는 응답이 86400초(24시간) 동안 유효함을 나타냅니다. 유효 기간 내에 브라우저는 동일한 요청에 대해 실행 전 요청을 다시 시작할 필요가 없습니다. 브라우저 자체에서는 최대 유효 시간을 유지하고 있으므로 이 헤더 필드의 값이 최대 유효 시간을 초과하면 적용되지 않습니다. 🎜🎜비행 전 요청이 완료된 후 실제 요청을 보냅니다: 🎜rrreee위 내용은 실행 전 요청에 대한 간략한 토론의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!