iOS 網路請求劫持
阿新 • • 發佈:2019-01-05
1、概述:
NSURLProtocol是URL loading system 中的一個重要的組成部分,它允許我們對全域性的網路請求(基於使用URLRequest)做攔截,可攔截的請求型別有NSURLConnection、NSURLSession 和 UIWebView中的請求。對於WKWebView的請求,它是無能為力的。
成功攔截網路請求後,有且不侷限於如下:
忽略網路請求,直接返回自定義的Response
修改request(請求地址,認證資訊等等)
為了測試對HTTP返回內容進行mock和stub
建立本地代理服務,用於資料變化時對URL請求的更改
故意製造畸形或非法返回資料來測試程式的魯棒性
過濾請求和返回中的敏感資訊
在既有協議基礎上完成對 NSURLConnection 的實現且與原邏輯不產生矛盾
2、實現
2.1需要從URLProtocol派生自己的協議類,那麼必須重寫以下四個方法
2.2再使用NSURLConnection或NSURLSession結合client物件處理該請求,使用client物件,將請求相關的結果返回URL loading system@objc class CustomURLProtocol: URLProtocol { override class func canInit(with:URLRequest) -> Bool { // 是否攔截請求,再做處理 if let url = with.url { if with.url!.host == "your host" { return true } } return false } override class func canonicalRequest(for: URLRequest) ->URLRequest { return `for` } override func startLoading() { self.stopLoading() } override func stopLoading() { self.client?.urlProtocolDidFinishLoading(self) } override class func requestIsCacheEquivalent(_ a: URLRequest, to b: URLRequest) -> Bool { return true } }
以URLConnection為例:
func connection(_ connection: NSURLConnection, didFailWithError error: Error) { self.client?.urlProtocol(self, didFailWithError: error) } func connection(_ connection: NSURLConnection, didReceive response: URLResponse) { self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) } func connection(_ connection: NSURLConnection, didReceive data: Data) { self.client?.urlProtocol(self, didLoad: data) } func connectionDidFinishLoading(_ connection: NSURLConnection) { self.client?.urlProtocolDidFinishLoading(self) }
3、註冊自定義的協議名
如果你使用的是OC,可以在自定義類中的重寫+load()
+ (void)load {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSURLProtocol registerClass:self];
});
}
如果你使用的是Swift,需要在app進行網路請求之前完成註冊:
URLProtocol.registerClass(CustomURLProtocol.classForCoder())
詳細的Demo可以參照: