>  기사  >  웹 프론트엔드  >  실행 전 요청에 대한 간략한 토론

실행 전 요청에 대한 간략한 토론

一个新手
一个新手원래의
2017-09-18 10:24:314603검색


실행 전 요청에 대한 간략한 토론

Background

가끔 백그라운드 인터페이스를 호출할 때 아래와 같이 두 번 요청한다는 사실을 눈치채셨는지 모르겠습니다.

실행 전 요청에 대한 간략한 토론

사실 우리가 처음 보내는 것은 실행 전 요청( 실행 전 요청), 이 문서에서는 실행 전 요청이 전송되는 이유, 실행 전 요청이 전송되는 시기, 실행 전 요청이 수행하는 작업에 대해 설명합니다

1 실행 전 요청이 전송되는 이유

우리 모두는 브라우저의 동일 출처 정책은 보안상의 이유로 브라우저가 스크립트에서 시작된 도메인 간 HTTP 요청을 제한합니다. XMLHttpRequest 및 Fetch는 모두 동일 출처 정책을 따릅니다.
일반적으로 브라우저가 교차 도메인 요청을 제한하는 방법에는 두 가지가 있습니다.
1. 브라우저는 교차 도메인 요청의 시작을 제한합니다.
2. 교차 도메인 요청은 정상적으로 시작될 수 있지만 반환된 결과는 브라우저에 의해 차단됩니다.

일반적으로 브라우저는 교차 도메인 요청을 제한하는 두 번째 방법을 사용합니다. 즉, 요청이 서버에 도달하여 데이터베이스의 데이터에 대해 작동했을 수 있지만 반환된 결과가 브라우저에 의해 차단되었습니다. 반환된 결과를 얻지 못했습니다. 이는 일회성 요청이 실패했지만 데이터베이스의 데이터에 영향을 미쳤을 수 있습니다.

이런 일이 발생하는 것을 방지하기 위해 사양에서는 서버 데이터에 부작용이 있을 수 있는 이 HTTP 요청 메서드에 대해 브라우저가 먼저 OPTIONS 메서드를 사용하여 사전 요청을 시작하여 학습하도록 요구합니다. 서버 정보 교차 도메인 요청을 허용할지 여부: 허용되면 데이터가 포함된 실제 요청을 보냅니다. 그렇지 않으면 데이터가 포함된 실제 요청이 전송되지 않습니다.

OPTIONS方法发起一个预检请求,从而获知服务器是否允许该跨域请求:如果允许,就发送带数据的真实请求;如果不允许,则阻止发送带数据的真实请求。

二. 什么时候发预检请求

HTTP请求包括: 简单请求 和 需预检的请求

1. 简单请求

简单请求不会触发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。其它浏览器并不支持这些额外的限制,因为它们不属于规范的一部分。

2.需预检的请求

“需预检的请求”要求必须首先使用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/plain2. 실행 전 요청을 보내는 경우

🎜HTTP 요청에는 다음이 포함됩니다: 단순 요청 및 실행 전 요청🎜
1. 단순 요청
🎜간단한 요청은 CORS 실행 전 요청을 트리거하지 않습니다. "Jian은 🎜에 속합니다. "단일 요청"이라는 용어는 Fetch 사양(CORS가 정의된 곳)에 속하지 않습니다. 🎜다음 조건이 모두 충족되면 요청은 "단순 요청"으로 간주될 수 있습니다. - 다음 방법 중 하나를 사용하세요: 🎜 - 받기 🎜 - 헤드 🎜 - 포스트 🎜 - 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 헤더에 대해 블랙리스트 모델로 전환합니다. 다른 브라우저는 사양에 포함되지 않기 때문에 이러한 추가 제한 사항을 지원하지 않습니다. 🎜
2. 사전 비행이 필요한 요청
🎜 "사전 비행이 필요한 요청"에서는 먼저 OPTIONS 메서드를 사용하여 서비스 영역에 대한 사전 비행 요청을 시작해야 합니다. 서버가 실제 요청을 허용했는지 여부. "실행 전 요청"을 사용하면 도메인 간 요청이 서버의 사용자 데이터에 예기치 않은 영향을 미치는 것을 방지할 수 있습니다. 🎜🎜요청이 다음 조건 중 하나라도 충족되면 먼저 실행 전 요청을 보내야 합니다. 🎜 - 다음 HTTP 방법 중 하나를 사용합니다: 🎜 - PUT 🎜 - 삭제 🎜 - 연결 🎜 - 옵션 🎜 - TRACE 🎜 - PATCH 🎜- CORS 안전 헤더 필드 세트 이외의 헤더 필드를 인위적으로 설정합니다. 컬렉션은 다음과 같습니다: 🎜 - 수락 🎜 - 수락 언어 🎜 - 콘텐츠 언어 🎜 - 콘텐츠 유형 🎜 - DPR 🎜 - 다운링크 🎜 - 데이터 저장 🎜 - 뷰포트 너비 🎜 - 너비 🎜 - Content-Type 값이 다음 중 하나에 속하지 않습니다. 🎜 - application/x-www-form-urlencoded 🎜 - 다중 부분/양식 데이터 🎜 - 텍스트/일반🎜

다음은 실행 전 요청을 수행해야 하는 HTTP 요청입니다.

var invocation = new XMLHttpRequest();
var url = ' 
var body = &#39;<?xml version="1.0"?><person><name>Arun</name></person>&#39;;function callOtherDomain(){
  if(invocation)
    {
      invocation.open(&#39;POST&#39;, url, true);
      invocation.setRequestHeader(&#39;X-PRODUCT&#39;, &#39;H5&#39;);
      invocation.setRequestHeader(&#39;Content-Type&#39;, &#39;application/xml&#39;);
      invocation.onreadystatechange = handler;
      invocation.send(body); 
    }
}
......

위 코드는 POST 요청을 사용하여 사용자 정의 헤더 필드(X-PRODUCT:H5)가 포함된 XML 문서를 보냅니다. 또한 요청의 Content-Typeapplication/xml입니다. 따라서 요청은 먼저 "실행 전 요청"을 시작해야 합니다.
실행 전 요청에 대한 간략한 토론Content-Typeapplication/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-PINGOTHERContent-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&#39;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-PINGOTHERContent-Type 필드의 전달을 허용함을 나타냅니다. 요청에. Access-Control-Allow-Methods와 마찬가지로 Access-Control-Allow-Headers 값은 쉼표로 구분된 목록입니다. 🎜🎜마지막으로 헤더 필드 🎜🎜Access-Control-Max-Age는 응답이 86400초(24시간) 동안 유효함을 나타냅니다. 유효 기간 내에 브라우저는 동일한 요청에 대해 실행 전 요청을 다시 시작할 필요가 없습니다. 브라우저 자체에서는 최대 유효 시간을 유지하고 있으므로 이 헤더 필드의 값이 최대 유효 시간을 초과하면 적용되지 않습니다. 🎜🎜비행 전 요청이 완료된 후 실제 요청을 보냅니다: 🎜rrreee

위 내용은 실행 전 요청에 대한 간략한 토론의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.