問(wèn)題描述
在某個(gè)地區(qū) DNS被污染的前提下,業(yè)務(wù)側(cè)希望webView也可以通過(guò)走cronet長(zhǎng)連接(ip直連)+gslb來(lái)跳過(guò)local dns那一步咱筛,但后續(xù)實(shí)施的時(shí)候發(fā)現(xiàn)某個(gè)webView頁(yè)面下的某些js請(qǐng)求響應(yīng)碼雖然是200彼妻,但是卻沒(méi)有接收到任何數(shù)據(jù)內(nèi)容嫌佑,前端頁(yè)面提示接口請(qǐng)求異常。
雙端差異
上面都是走cronet和長(zhǎng)連接的訪問(wèn)侨歉,為啥ios沒(méi)問(wèn)題而android有問(wèn)題呢屋摇?和同事重現(xiàn)下路徑發(fā)現(xiàn),ios那邊是在web.xx.com下面用sapi.xx.com去發(fā)起接口請(qǐng)求幽邓,是沒(méi)有Options方法發(fā)起的炮温,但是android的webView下的web.xx.com頁(yè)面下的每個(gè)sapi.xx.com每次Get/Post請(qǐng)求都會(huì)發(fā)起Options請(qǐng)求,和業(yè)務(wù)服務(wù)求助該sapi.xx.com資源請(qǐng)求是否可以執(zhí)行跨域操作牵舵。
簡(jiǎn)單科普下什么是跨域:在A域名網(wǎng)站下柒啤,但是里面的js請(qǐng)求卻使用了B域名做資源請(qǐng)求簡(jiǎn)稱跨域請(qǐng)求倦挂。如果js也是用A域名做資源請(qǐng)求就不會(huì)跨域。
問(wèn)題相關(guān)描述
http基礎(chǔ)知識(shí)
請(qǐng)求頭:
Origin
: 表示了請(qǐng)求的來(lái)源
Referer
: 請(qǐng)求頭包含了當(dāng)前請(qǐng)求頁(yè)面的來(lái)源頁(yè)面的地址担巩,即表示當(dāng)前頁(yè)面是通過(guò)此來(lái)源頁(yè)面里的鏈接進(jìn)入的方援。
Access-Control-Request-Method
: 請(qǐng)求頭 **Access-Control-Request-Method**
出現(xiàn)于 preflight request(預(yù)檢請(qǐng)求)中,用于通知服務(wù)器在真正的請(qǐng)求中會(huì)采用哪種 HTTP 方法涛癌。
Access-Control-Request-Headers
: 請(qǐng)求頭 **Access-Control-Request-Headers**
出現(xiàn)于 preflight request(預(yù)檢請(qǐng)求)中肯骇,用于通知服務(wù)器在真正的請(qǐng)求中會(huì)采用哪些請(qǐng)求頭。
響應(yīng)頭:
Access-Control-Allow-Origin
: **Access-Control-Allow-Origin**
響應(yīng)標(biāo)頭指定了該響應(yīng)的資源是否被允許與給定的來(lái)源(origin)共享祖很。(對(duì)應(yīng)Origin笛丙,說(shuō)明運(yùn)行在哪個(gè)網(wǎng)頁(yè)下執(zhí)行跨域請(qǐng)求)
Access-Control-Allow-Methods
:響應(yīng)首部 **Access-Control-Allow-Methods**
在對(duì) preflight request.(預(yù)檢請(qǐng)求)的應(yīng)答中明確了客戶端所要訪問(wèn)的資源允許使用的方法或方法列表。(支持哪些跨域的http方法)
Access-Control-Allow-Headers
: 響應(yīng)首部 **Access-Control-Allow-Headers**
用于 preflight request(預(yù)檢請(qǐng)求)中假颇,列出了將會(huì)在正式請(qǐng)求的 Access-Control-Request-Headers 字段中出現(xiàn)的首部信息胚鸯。
Access-Control-Allow-Credentials
:**Access-Control-Allow-Credentials**
響應(yīng)頭用于在請(qǐng)求要求包含 credentials(Request.credentials 的值為 include
)時(shí),告知瀏覽器是否可以將對(duì)請(qǐng)求的響應(yīng)暴露給前端 JavaScript 代碼笨鸡。(允許跨域行為會(huì)返回true)
跨域訪問(wèn)過(guò)程
- 在A網(wǎng)頁(yè)下面姜钳,用了B域名進(jìn)行Get的資源請(qǐng)求(命名為B1),這時(shí)候?yàn)g覽器會(huì)用B1會(huì)自動(dòng)發(fā)起Options請(qǐng)求(命名為B2)形耗,B2會(huì)帶上Origin哥桥、Refer、Access-Control-Request-Method激涤、Access-Control-Headers等必要請(qǐng)求頭訪問(wèn)服務(wù)端拟糕,服務(wù)端允許該B2請(qǐng)求在A網(wǎng)頁(yè)下面進(jìn)行跨域操作,就會(huì)在響應(yīng)頭里面插入access_control_allow_origin 倦踢、access_control_methods送滞、access_control_allow_headers、 access_control_allow_credentials : true(運(yùn)行進(jìn)行跨域操作)
- 獲取到響應(yīng)頭4個(gè)核心的key和value后辱挥,瀏覽器才會(huì)用B1進(jìn)行發(fā)起真實(shí)的業(yè)務(wù)請(qǐng)求犁嗅,這時(shí)候B1往頭部access_control_request_headers里面聲明過(guò)的key才允許塞入口頭部進(jìn)行請(qǐng)求,最終B1的響應(yīng)頭也會(huì)包含access_control_allow_origin 晤碘、access_control_methods褂微、access_control_allow_headers、 access_control_allow_credentials這最重要的4個(gè)頭部信息园爷,如果缺少一個(gè)網(wǎng)絡(luò)層都認(rèn)為不安全宠蚂,都不會(huì)正確返回業(yè)務(wù)數(shù)據(jù)。
解決辦法
本身跨域問(wèn)題都是需要經(jīng)過(guò)服務(wù)端去審核此次行為是否安全腮介,所以不該是客戶端解決肥矢。所以應(yīng)該由長(zhǎng)連接的服務(wù)端把Options的請(qǐng)求轉(zhuǎn)發(fā)到具體業(yè)務(wù)去校驗(yàn)其安全性,不應(yīng)該簡(jiǎn)單的把Options請(qǐng)求返回200就結(jié)束了叠洗。
排查問(wèn)題思路
- 對(duì)比成功/失敗兩個(gè)請(qǐng)求頭和響應(yīng)頭的差距甘改,把字節(jié)流內(nèi)容打印出來(lái)。
- 嘗試代碼寫(xiě)死缺少的請(qǐng)求頭和響應(yīng)頭灭抑,復(fù)現(xiàn)相同場(chǎng)景下是否可以解決該問(wèn)題十艾。