NSURLSession跨域重定向透?jìng)鱄TTP Header問(wèn)題解決
背景
在源網(wǎng)頁(yè)通過(guò)服務(wù)器重定向打開(kāi)某個(gè)三方網(wǎng)頁(yè),網(wǎng)絡(luò)層出現(xiàn)了 -1005 (NSURLErrorNetworkConnectionLost) 錯(cuò)誤碼,排查差異后發(fā)現(xiàn)是由于給這個(gè)三方服務(wù)帶了源網(wǎng)頁(yè)特有的 HTTP Header,導(dǎo)致服務(wù)器檢查異常從而斷開(kāi)連接。
核心原因是跨域重定向場(chǎng)景透?jìng)髁?Header 帶到了三方服務(wù),這有些不符合常理,會(huì)帶來(lái)兩個(gè)明顯的問(wèn)題:
- 敏感 HTTP Header 傳遞給三方服務(wù),存在隱私安全問(wèn)題;
- 服務(wù)收到未預(yù)期的 HTTP Header,可能被視為非法訪問(wèn),導(dǎo)致網(wǎng)頁(yè)異常;
系統(tǒng)庫(kù)如何設(shè)計(jì)的
NSURLSession 在跨域重定向場(chǎng)景默認(rèn)會(huì)透?jìng)?HTTP Header,參考 Swift 在 _HTTPURLProtocol 的相關(guān)處理:
/// If the response is a redirect, return the new request
/// RFC 7231 section 6.4 defines redirection behavior for HTTP/1.1
/// - SeeAlso: <https://tools.ietf.org/html/rfc7231#section-6.4>
func redirectRequest(for response: HTTPURLResponse, fromRequest: URLRequest) -> URLRequest? {
//TODO: Do we ever want to redirect for HEAD requests?
guard
let location = response.value(forHeaderField: .location),
let targetURL = URL(string: location)
else {
// Can't redirect when there's no location to redirect to.
return nil
}
var request = fromRequest
// Check for a redirect:
switch response.statusCode {
case 301...302 where request.httpMethod == "POST", 303:
// Change "POST" into "GET" but leave other methods unchanged:
request.httpMethod = "GET"
request.httpBody = nil
case 301...302, 305...308:
// Re-use existing method:
break
default:
return nil
}
// If targetURL has only relative path of url, create a new valid url with relative path
// Otherwise, return request with targetURL ie.url from location field
guard targetURL.scheme == nil || targetURL.host == nil else {
request.url = targetURL
return request
}
… (后面是相對(duì)路徑處理)
}
大致處理流程為:
- 取出響應(yīng)頭 Location 字段作為目標(biāo) URL;
- 若為 POST 請(qǐng)求改為 GET 請(qǐng)求并清空其 Body;
- 若目標(biāo) URL 為相對(duì)路徑,補(bǔ)齊完整 URL;
可以看到重定向后的請(qǐng)求會(huì)直接繼承 HTTP Header,這個(gè)處理遵循了 RFC 7231 的規(guī)范,大致去翻了一下,只描述了 Location header field 的處理方法,而沒(méi)有說(shuō)明其它請(qǐng)求頭該如何處理,在 Chrome 下重定向場(chǎng)景應(yīng)該是直接丟棄之前的 Header 的。
我們知道有一個(gè)公開(kāi)代理方法…willPerformHTTPRedirection…可以去改變重定向請(qǐng)求,但如果不借助網(wǎng)絡(luò)攔截技術(shù),WebKit 里面的請(qǐng)求也無(wú)法修改,順便看一下 WebKit 內(nèi)部是否對(duì)這種場(chǎng)景有所處理。
WebKit 是在 NetworkSessionCocoa 類里面承載 NSURLSession 請(qǐng)求的,實(shí)現(xiàn)了URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:協(xié)議,順著處理鏈路從 Network 進(jìn)程跟到 Web 進(jìn)程再跟到 APP 進(jìn)程,都沒(méi)有找到關(guān)于跨域重定向清理 HTTP Header 的處理,更不用說(shuō)公開(kāi)配置能力了。
解決方案
針對(duì) WebView 需要跨域重定向的場(chǎng)景,如何避免私有 HTTP Header 傳遞給目標(biāo)請(qǐng)求服務(wù)?
方案一
如果前置請(qǐng)求是為了做統(tǒng)計(jì)上報(bào),那可以直接跳轉(zhuǎn)到目標(biāo) URL,前置請(qǐng)求旁路去處理;如果前置請(qǐng)求是為了獲取跳轉(zhuǎn)的地址,那么可以發(fā)起一個(gè) Ajax 請(qǐng)求拿到回包后去跳轉(zhuǎn)目標(biāo) URL。
或者更直接的,把 server-side redirect 改為 client-side redirect,讓前置請(qǐng)求返回文檔,文檔內(nèi)部進(jìn)行document.replace()等函數(shù)跳轉(zhuǎn)到目標(biāo) URL,但這種處理會(huì)讓性能劣化,并且會(huì)導(dǎo)致前置請(qǐng)求關(guān)聯(lián)的 Web 進(jìn)程歷史棧緩存被清理
核心思想就是避免服務(wù)器跨域重定向,由于和 Chrome 內(nèi)核表現(xiàn)不一致且前端改造成本較大,一般較難實(shí)施,但這對(duì)于沒(méi)有 WebKit 網(wǎng)絡(luò)攔截技術(shù)的 APP 來(lái)說(shuō)可能是唯一思路。
方案二
如果有 WebKit 網(wǎng)絡(luò)攔截技術(shù),那處理就比較簡(jiǎn)單了,只需要保證在重定向請(qǐng)求發(fā)起之前,如果主域名發(fā)生變化,就把 APP 私有的請(qǐng)求頭清理掉,較簡(jiǎn)單的規(guī)避系統(tǒng)設(shè)計(jì)問(wèn)題。
以上就是NSURLSession跨域重定向透?jìng)鱄TTP Header問(wèn)題解決的詳細(xì)內(nèi)容,更多關(guān)于NSURLSession跨域重定向的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
ios 使用xcode11 新建項(xiàng)目工程的步驟詳解
這篇文章主要介紹了ios 使用xcode11 新建項(xiàng)目工程 (值得注意的問(wèn)題),本文分步驟通過(guò)圖文的形式給大家展示,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04
iOS應(yīng)用開(kāi)發(fā)中圖片的拉伸問(wèn)題解決方案
這篇文章主要介紹了iOS應(yīng)用開(kāi)發(fā)中圖片的拉伸問(wèn)題解決方案,有時(shí)圖片的拉伸只需要拉伸中間部分而不拉伸兩端,這是本文所關(guān)注的問(wèn)題,需要的朋友可以參考下2016-02-02
IOS開(kāi)發(fā)過(guò)程中的消息通知--小紅點(diǎn)
本文主要介紹了IOS開(kāi)發(fā)過(guò)程中的消息通知--小紅點(diǎn)的相關(guān)知識(shí)。大致分為兩種方法:系統(tǒng)方法和自定義方法。下面跟著小編一起來(lái)看下吧2017-04-04
查看iOS已上架App的Crash信息定位、應(yīng)對(duì)處理方式的實(shí)例
下面小編就為大家?guī)?lái)一篇查看iOS已上架App的Crash信息定位、應(yīng)對(duì)處理方式的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
iOS開(kāi)發(fā)之App主題切換解決方案完整版(Swift版)
這篇文章主要為大家詳細(xì)介紹了iOS開(kāi)發(fā)之App主題切換完整解決方案,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
iOS多線程應(yīng)用開(kāi)發(fā)中自定義NSOperation類的實(shí)例解析
這篇文章主要介紹了iOS多線程應(yīng)用開(kāi)發(fā)中自定義NSOperation類的實(shí)例解析,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2016-01-01
IOS實(shí)現(xiàn)視頻動(dòng)畫(huà)效果的啟動(dòng)圖
這篇文章實(shí)現(xiàn)的是一個(gè)關(guān)于啟動(dòng)頁(yè)或者引導(dǎo)頁(yè)的視頻動(dòng)畫(huà)效果的實(shí)現(xiàn)過(guò)程,對(duì)于大家開(kāi)發(fā)APP具有一定的參考借鑒價(jià)值,有需要的可以來(lái)看看。2016-09-09
iOS判斷網(wǎng)絡(luò)請(qǐng)求超時(shí)的方法
本篇文章主要介紹了iOS判斷網(wǎng)絡(luò)請(qǐng)求超時(shí)的方法,現(xiàn)在分享給大家,也給大家做個(gè)參考。感興趣的小伙伴們可以參考一下。2016-12-12

