iOS 抓包原理

攔截原理:

  • NSURLProtocol 是蘋果為我們提供的 URL Loading System 的一部分,在每一個 HTTP 請求開始時,URL 加載系統(tǒng)創(chuàng)建一個合適的 NSURLProtocol 對象處理對應(yīng)的 URL 請求,而我們需要做的就是寫一個繼承自 NSURLProtocol 的類,并通過 - registerClass: 方法注冊我們的協(xié)議類,然后 URL 加載系統(tǒng)就會在請求發(fā)出時使用我們創(chuàng)建的協(xié)議對象對該請求進(jìn)行處理。
// 1.注冊我們的協(xié)議類
[NSURLProtocol registerClass:[DLCustomURLProtocol class]];

### 攔截方法的介紹:
// 2.是否能夠處理給定的請求
+ (BOOL)canInitWithRequest:(NSURLRequest *)request;

// 3.處理URL轉(zhuǎn)換為IP地址
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request;

// 4.開始網(wǎng)絡(luò)請求
- (void)startLoading;

// 5.結(jié)束網(wǎng)絡(luò)請求
- (void)stopLoading;

// 6.處理網(wǎng)絡(luò)請求的code
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
                                 didReceiveResponse:(NSURLResponse *)response
                                  completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler;

// 7.處理網(wǎng)絡(luò)請求的返回信息
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error;

WKWebView使用私有API的原因:

  • WKURLSchemeHandler是iOS11就推出的,用于處理自定義請求的方案,不過并不能處理HTTP、HTTPS等常規(guī)scheme。但是現(xiàn)在有另外一個方法,就是去 WKWebview的initWithFrame:方法,然后設(shè)置一個WKURLSchemeHandler給WKWebview實例,這樣就能截獲WKWebview的HTTP和HTTPS請求了。
    WebKit 進(jìn)程是獨立于 app 進(jìn)程之外的,兩個進(jìn)程之間使用消息隊列的方式進(jìn)行進(jìn)程間通信。比如 app 想使用 WKWebView 加載一個請求,就要把請求的參數(shù)打包成一個 Message,然后通過 IPC 把 Message 交給 WebKit 去加載,反過來 WebKit 的請求想傳到 app 進(jìn)程的話(比如 URLProtocol ),也要打包成 Message 走 IPC。出于性能的原因,打包的時候 HTTPBody 和 HTTPBodyStream 這兩個字段被丟棄掉了,這個可以參考 WebKit 的源碼,這就導(dǎo)致 -[WKWebView loadRequest:] 傳出的 HTTPBody 和 NSURLProtocol 傳回的 HTTPBody 全都被丟棄掉了。所以如果通過 NSURLProtocol 注冊攔截 http scheme,那么由 WebKit 發(fā)起的所有 http POST 請求就全都無效了.
#pragma mark - WKWebView的私有API
#pragma mark - 以下方法為iOS的私有方法,建議上線時注釋————以下全部代碼
+ (void)DL_unregisterScheme {
    [self wk_registerScheme:@"http"];
    [self wk_registerScheme:@"https"];
}

FOUNDATION_STATIC_INLINE Class ContextControllerClass() {
    static Class cls;
    if (!cls) {
        cls = [[[WKWebView new] valueForKey:@"browsingContextController"] class];
    }
    return cls;
}

FOUNDATION_STATIC_INLINE SEL RegisterSchemeSelector() {
    return NSSelectorFromString(@"registerSchemeForCustomProtocol:");
}

+ (void)wk_registerScheme:(NSString *)scheme {
    Class cls = ContextControllerClass();
    SEL sel = RegisterSchemeSelector();
    if ([(id)cls respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
    }
}

抓取第三方AFN請求

  • 對于NSURLSession的網(wǎng)絡(luò)請求,需要替換protocolClasses方法
+ (void)exchangeAFNSessionConfiguration {
    Class cls = NSClassFromString(@"__NSCFURLSessionConfiguration") ?: NSClassFromString(@"NSURLSessionConfiguration");
    Method originalMethod = class_getInstanceMethod(cls, @selector(protocolClasses));
    Method stubMethod = class_getInstanceMethod([DLCustomURLProtocol class], @selector(protocolClasses));
    if (!originalMethod || !stubMethod) {
        CLog(@"Couldn't load NEURLSessionConfiguration");
        return;
    }
    method_exchangeImplementations(originalMethod, stubMethod);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容