前言:開發(fā)時設置手機代理抓接口請求時,打開H5頁面唾那,總是會看到OPTIONS請求,特此學習記錄一下。
1. 作用
-
請求服務器返回所支持的所有HTTP請求方法闹获;
示例:
$ curl -X OPTIONS http://example.org -i
HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST #
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Thu, 14 Jul 2022 06:15:30 GMT
Expires: Thu, 21 Jul 2022 06:15:30 GMT
Server: EOS (vny/0453)
Content-Length: 0
響應報文包含一個 Allow
首部字段期犬,該字段的值表明了服務器支持的所有 HTTP 方法。
-
跨域請求的預檢請求避诽;
下面????會詳細介紹同源策略龟虎、跨域請求、OPTIONS請求沙庐。
2. 跨域請求
2.1 同源策略
如果兩個URL的協(xié)議鲤妥、主機、端口都相同拱雏,則稱這兩個URL同源棉安。以http://music.javaswing.cn/home/index.html為例:
作用:這種同源策略就是瀏覽器的一個安全機制,主要是限制html或者它加載的js在沒有明確授權的情況下铸抑,不能讀寫其它源origin的資源贡耽,它能幫助阻隔惡意html,減少可能被攻擊的媒介鹊汛。但是實際開發(fā)時蒲赂,會有需要跨域的業(yè)務,就有了CORS的出現(xiàn)刁憋。
2.2 CORS(Cross Origin Resource Sharing) 跨域資源共享
CORS 跨域資源共享是一個W3C標準滥嘴,允許瀏覽器向跨源服務器發(fā)送XMLHttpRequest請求。它使用額外的HTTP頭告訴瀏覽器至耻,讓運行在一個origin上的web應用被準許訪問來自不同源服務器上的指定的資源若皱。當一個資源從與該資源本身所在的服務器不同的域、協(xié)議有梆、或端口請求一個資源時是尖,資源會發(fā)起一個跨域HTTP請求意系。
簡單來說泥耀,就是CORS允許在https://www.aa.com/a/a.html的網(wǎng)頁中,去請求https://www.bb.com/bb的接口獲取數(shù)據(jù)蛔添。
瀏覽器將CORS請求分成兩類:簡單請求和非簡單請求痰催。
簡單請求:
- 請求方法為:HEAD/GET/POST
- HTTP的頭信息不超過以下幾個字段:Accept、Accept-Language迎瞧、Content-Language夸溶、Last-Event-ID、Content-Type(只限于三個值application/x-www-form-urlencoded凶硅、mutipart/form-data缝裁、text/plain)
非簡單請求:
凡是不同時滿足上面兩個條件的,就屬于非簡單請求足绅。
瀏覽器對這兩種請求的處理是不一樣的:
簡單請求:
- 在請求中需要附加一個額外的Origin頭部捷绑,其中包含請求頁面的源信息(協(xié)議韩脑、域名、端口號)粹污,便于服務器根據(jù)這個頭部信息決定是否給予響應段多;
- 如果服務器認為這個請求可以接口,就在Access-Control-Allow-Origin頭部中回發(fā)相同的源信息(如果是公共資源壮吩,可以設置 *)进苍;
- 沒有這個頭部或者源信息不匹配,瀏覽器就會駁回請求鸭叙,正常情況下觉啊,瀏覽器會處理請求。注意:請求和響應都不包含cookie信息沈贝;
- 如果需要包含cookie信息柄延,ajax請求需要設置xhr的屬性withCredentials為true,服務器需要設置響應頭部 Access-Control-Allow-Credentials: true;
非簡單請求:
瀏覽器在發(fā)送真正的請求之前缀程,會先發(fā)送一個Preflight請求給服務器搜吧,這種請求使用OPTIONS方法,下面會展開進行介紹杨凑。
3. OPTIONS預檢請求
3.1 OPTIONS預檢請求的觸發(fā)條件
上面了解了同源策略和CORS滤奈,終于到了OPTIONS請求。在CORS機制下一個域名A要訪問域名B的服務撩满,在使用非簡單請求之前蜒程,會先進行一個預檢請求(瀏覽器自動發(fā)起),檢查B服務是否允許跨域請求伺帘,服務確認之后昭躺,才會發(fā)起真正的HTTP請求。
同時伪嫁,在預檢請求的返回中领炫,服務端也可以通知客戶端,是否需要攜帶身份憑證(包括Cookies和HTTP認證相關數(shù)據(jù))张咳。
3.2 OPTIONS預檢請求結構
3.2.1 OPTIONS預檢請求頭
OPTIONS預檢請求會攜帶幾個關鍵的Request Header:
Request Header | 作用 |
---|---|
Access-Control-Request-Method | 告訴服務器實際請求所使用的 HTTP 方法 |
Access-Control-Request-Headers | (可選)告訴服務器實際請求所攜帶的自定義首部字段 |
Origin | 發(fā)起請求的域名 (協(xié)議帝洪、域名、端口號),便于服務器根據(jù)這個頭部信息決定是否給予響應 |
{
"Host": "app.aaa.com",
"Origin": "https://m.bbb.com",
"Access-Control-Request-Method": "GET",
"Access-Control-Request-Headers": "csrf-token",
"Connection": "keep-alive",
"Accept": "*/*",
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 zzhunter",
"Referer": "https://m.caihuoxia.com/",
"Accept-Language": "zh-CN,zh-Hans;q=0.9",
"Accept-Encoding": "gzip"
}
3.2.2 OPTIONS預檢響應頭
當收到一個預檢請求之后脚猾,服務器可以決定是否允許這種類型的請求葱峡。服務器通過在響應中發(fā)送如下頭部信息與瀏覽器進行溝通。預檢響應頭的關鍵字段:
response header | 作用 |
---|---|
Access-Control-Allow-Methods | 返回了服務端允許的請求龙助,包含 GET/HEAD/PUT/PATCH/POST/DELETE |
Access-Control-Allow-Credentials | 允許跨域攜帶 cookie(跨域請求要攜帶 cookie 必須設置為 true) |
Access-Control-Allow-Origin | 允許跨域請求的域名砰奕,這個可以在服務端配置一些信任的域名白名單 |
Access-Control-Allow-Headers | 客戶端請求所攜帶的自定義首部字段 |
Access-Control-Max-Age | 應該將這個 Preflight 請求緩存多長時間(以秒表示) |
{
"Server": "Tengine",
"Date": "Thu, 14 Jul 2022 06:25:07 GMT",
"Content-Type": "text/plain; charset=utf-8",
"Content-Length": "0",
"Connection": "keep-alive",
"Access-Control-Allow-Origin": "https://m.bbb.com",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Headers": "PPU,t,tk,v,uid,Content-Type,Csrf-Token",
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
"Access-Control-Max-Age": "1728000",
"Set-Cookie": [
"id58=c5/nR2LPtsOJbsB8a+YHAg==; expires=Sat, 13-Jul-24 06:25:07 GMT; domain=caihuoxia.com; path=/"
],
"P3P": "policyref=\"/w3c/p3p.xml\", CP=\"CUR ADM OUR NOR STA NID\""
}
一旦服務器通過Preflight 請求允許該請求之后,以后每次瀏覽器正常的CORS請求,都跟簡單請求一樣了军援。
4. OPTIONS預檢請求優(yōu)化
上面了解到常空,跨域請求會觸發(fā)兩次請求:OPTIONS預檢請求、真正的請求盖溺。可以通過緩存OPTIONS預檢請求的結果漓糙,來減少請求的數(shù)量。
Access-Control-Max-Age
這個響應首部表示預檢請求的返回結果(即 Access-Control-Allow-Methods
和 Access-Control-Allow-Headers
提供的信息) 可以被緩存的最長時間烘嘱,單位是秒昆禽。
如果值為 -1,則表示禁用緩存蝇庭,每一次請求都需要提供預檢請求醉鳖,即用 OPTIONS 請求進行檢測。
5. 總結
OPTIONS預檢請求哮内,可用于檢測服務器允許的http方法盗棵。另外,當發(fā)起跨域請求時北发,非簡單請求會導致瀏覽器自動發(fā)起一次OPTIONS預檢請求纹因,服務器接受該跨域請求之后,瀏覽器才繼續(xù)發(fā)起正式請求琳拨。
CORS的優(yōu)點:
- CORS通信與同源的AJAX通信沒有差別瞭恰,代碼完全一樣,容易維護狱庇;
- 支持所有類型的HTTP請求惊畏;
CORS的缺點:
- 存在兼容性問題,特別是IE10以下的瀏覽器密任;
- 第一次發(fā)送非簡單請求時會多一次請求颜启;