iOS端網絡攔截技術

iOS端網絡攔截技術

NSURLProtocol

NSURLProtocol是URL Loading System的重要組成部分,能夠攔截攔截所有基于URL Loading System的網絡請求。

URL-Loading-sys.png

可以攔截的網絡請求包括NSURLSession,NSURLConnection以及UIWebVIew。
基于CFNetwork的網絡請求,以及WKWebView的請求是無法攔截的。
代碼不夠完善Demo地址--https://github.com/softwarefaith/JiOSDNS

如何使用NSURLProtocol

NSURLProtocol是一個抽象類。創建他的一個子類:

 @interface AppDNSInterceptor : NSURLProtocol

分為五個步驟:
注冊 -> 攔截 -> 轉發 -> 回調 -> 完結

1.注冊

對于基于NSURLConnection或者使用[NSURLSession sharedSession]創建的網絡請求,調用registerClass方法即可。

[NSURLProtocol registerClass:[NSClassFromString(@"AppDNSInterceptor") class]];

對于基于NSURLSession的網絡請求,需要通過配置NSURLSessionConfiguration對象的protocolClasses屬性。

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.protocolClasses = @[[NSClassFromString(@"AppDNSInterceptor") class]];
2.攔截

是否要處理對應的請求。由于網頁存在動態鏈接的可能性,簡單的返回YES可能會創建大量的NSURLProtocol對象,因此我們需要保證每個請求能且僅能被返回一次YES.

+(BOOL)canInitWithRequest:(NSURLRequest *)request {}
+(BOOL)canInitWithTask:(NSURLSessionTask *)task { return [self canInitWithRequest:task.currentRequest];}

是否要對請求進行重定向,或者修改請求頭、域名等關鍵信息。返回一個新的NSURLRequest對象來定制業務

+(NSURLRequest *)canonicalRequestForRequest:    (NSURLRequest *)request {
//這里截取重定向 做定制化服務:比如修改頭部信息 ,dns映射ip等操作
NSMutableURLRequest *mutableRequest = [request mutableCopy];
return mutableRequest;

}

3.轉發
-(instancetype)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client {

AppDNSInterceptor *interceptor = [super initWithRequest:request cachedResponse:nil client:client];
return interceptor;}

-(void)startLoading {
NSMutableURLRequest * request = self.request.mutableCopy;
//    //給我們處理過的請求設置一個標識符, 防止無限循環,
[NSURLProtocol setProperty: @YES forKey: kAppDNSInterceptorKey inRequest: request];
self.connection = [NSURLConnection connectionWithRequest: request delegate: self];}
4.注回調

當網絡收到請求返回時,還需要在將返回值給原來網絡請求

-(void)URLProtocol:(NSURLProtocol *)protocol wasRedirectedToRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse;
-(void)URLProtocol:(NSURLProtocol *)protocol cachedResponseIsValid:(NSCachedURLResponse *)cachedResponse;
-(void)URLProtocol:(NSURLProtocol *)protocol didReceiveResponse:(NSURLResponse *)response cacheStoragePolicy:(NSURLCacheStoragePolicy)policy;
-(void)URLProtocol:(NSURLProtocol *)protocol didLoadData:(NSData *)data;
-(void)URLProtocolDidFinishLoading:(NSURLProtocol *)protocol;
-(void)URLProtocol:(NSURLProtocol *)protocol didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
-(void)URLProtocol:(NSURLProtocol *)protocol didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
5.完結
- (void)stopLoading {
[self.managerSession cancel];
self.managerSession = nil;}

代碼不夠完善Demo地址--https://github.com/softwarefaith/JiOSDNS

參考文章

  1. UIWebView 攔截js,css
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容