iOS小技能:【intercept the HTTP/HTTPS requests 】利用NSURLProtocol 攔截請求
“我正在參加「掘金·啟航計劃」”
前言
動手實踐:寫一個tweak ,修改請求的HTTPHeaderField
NSURLProtocol 只能攔截 UIURLConnection、NSURLSession 和 UIWebView 中的請求;
對於 WKWebView 中發出的網路請求也無能為力
,如果真的要攔截來自 WKWebView 中的請求,還是需要實現 WKWebView 對應的 WKNavigationDelegate,並在代理方法中獲取請求。
應用場景:
1、 自定義請求頭的HTTPHeaderField
2、針對NSURLSessionConfiguration設定代理和埠,讓一些特殊的請求走自定義的隧道IP和埠
I NSURLProtocol 攔截 HTTP 請求
1.1 NSURLProtocol 攔截 HTTP 請求的原理
An NSURLProtocol object handles the loading of protocol-specific URL data. The NSURLProtocol class itself is an abstract class that provides the infrastructure for processing URLs with a specific URL scheme. You create subclasses for any custom protocols or URL schemes that your app supports.
HTTP 請求開始時,URL 載入系統建立一個合適的 NSURLProtocol 物件處理對應的 URL 請求,因此我們只需寫一個繼承自 NSURLProtocol 的類,並通過 - registerClass: 方法註冊我們的協議類,然後 URL 載入系統就會在請求發出時使用我們建立的協議物件對該請求進行處理。
1.2 使用 NSURLProtocol 攔截 HTTP 請求
從CSDN下載Demo:https://download.csdn.net/download/u011018979/16753164
1、文章:https://kunnan.blog.csdn.net/article/details/115690756 2、原理:利用NSURLProtocol 攔截 HTTP 請求 3、應用場景:隧道APP請求我們自己介面的都不走隧道、修改請求的HTTPHeaderField,設定代理IP和埠、防抓包(使Thor,Charles,Burp等代理抓包方式全部失效) CustomHTTPProtocol
- 決定請求是否需要當前協議物件處理的方法
```objectivec /** 決定請求是否需要當前協議物件處理
/ +(BOOL)canInitWithRequest:(NSURLRequest )request{
if ([NSURLProtocol propertyForKey:protocolKey inRequest:request]) {
return NO;
}
NSString * url = request.URL.absoluteString;
return [self isUrl:url];
}
```
- 對當前的請求物件需要進行哪些處理
```objectivec + (NSURLRequest )canonicalRequestForRequest:(NSURLRequest )request;
```
修改NSURLRequest 物件:在CanonicalRequestForRequest 方法中,可以修改 request headers
- NSURLProtocol 如何例項化?
```objectivec
- (instancetype)initWithRequest:(NSURLRequest )request cachedResponse:(nullable NSCachedURLResponse )cachedResponse client:(nullable id
- app啟動的時候進行注入
objectivec
/! Call this to start the module. Prior to this the module is just dormant, and * all HTTP requests proceed as normal. After this all HTTP and HTTPS requests * go through this module. / - (BOOL)application:(UIApplication )application willFinishLaunchingWithOptions:(NSDictionary )launchOptions {
[CustomHTTPProtocol setDelegate:self];
if (YES) {
[CustomHTTPProtocol start];
}
} ```
II 動手實踐
原始碼獲取請關注【公號:iOS逆向】: 寫一個tweak ,修改請求的HTTPHeaderField
2.1 hook
```objectivec %hook AppDelegate
-
(BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions {
%log(); BOOL rect = %orig;
[CustomHTTPProtocol setDelegate:self]; if (YES) { [CustomHTTPProtocol start]; }
return rect; }
%end ```
2.2 針對NSURLSessionConfiguration設定代理和埠
```objectivec + (QNSURLSessionDemux *)sharedDemux { static dispatch_once_t sOnceToken; static QNSURLSessionDemux * sDemux; dispatch_once(&sOnceToken, ^{ NSURLSessionConfiguration * config;
config = [NSURLSessionConfiguration defaultSessionConfiguration];
// You have to explicitly configure the session to use your own protocol subclass here
// otherwise you don't see redirects <rdar://problem/17384498>.
pragma mark - ** 針對NSURLSessionConfiguration設定代理和埠
NSString* proxyHost = @"socks-";
// NSString* proxyHost = @"192.168.2.166";
NSNumber* proxyPort = [NSNumber numberWithInt: 8830 ];
// NSNumber* proxyPort = [NSNumber numberWithInt: 8888 ];
// Create an NSURLSessionConfiguration that uses the proxy
NSDictionary *proxyDict = @{
@"HTTPEnable" : @1,
(NSString *)kCFStreamPropertyHTTPProxyHost : proxyHost,
(NSString *)kCFStreamPropertyHTTPProxyPort : proxyPort,
@"HTTPSEnable" : @(1),
(NSString *)kCFStreamPropertyHTTPSProxyHost : proxyHost,
(NSString *)kCFStreamPropertyHTTPSProxyPort : proxyPort,
};
// NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
config.connectionProxyDictionary = proxyDict;
[config setHTTPAdditionalHeaders:@{
Authorizationkey:Authorizationvalue,
}
];
config.protocolClasses = @[ self ];
sDemux = [[QNSURLSessionDemux alloc] initWithConfiguration:config];
});
return sDemux;
}
```
2.3 測試
-
檢視請求頭資訊 ```objectivec %hook NSURLProtocol
-
(void)setProperty:(id)value forKey:(NSString )key inRequest:(NSMutableURLRequest )request{
%log(); %orig; }
%end
```
see also
- iOS APP 不走全域性proxy的方案【 例如:隧道APP的請求介面,一些自己特殊介面不走隧道】(利用NSURLProtocol 進行請求的攔截)
-
防代理 configuration.connectionProxyDictionary ```objectivec
//APP請求我們自己介面的都不走隧道 NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; configuration.connectionProxyDictionary = @{};
// 2/ AFHTTPSessionManager 建立NSURLSessionDataTask AFHTTPSessionManager *mgr = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:configuration];
```
- iOS小技能:UITableView的適配 (iOS10/iOS14/iOS16.0)
- iOS小技能:和uni-app、unity的融合方案
- iOS小技能:iOS15崩潰排查技巧(symbolicatecrash符號化分析問題、匯出和隱藏符號)
- iOS小技能:【intercept the HTTP/HTTPS requests 】利用NSURLProtocol 攔截請求
- iOS小技能: tweak 整合CocoaAsyncSocket(建連、斷開、重連、心跳、通用請求)
- iOS小技能:iOS13 證件掃描 & 文字識別API
- iOS小技能:整合下拉重新整理控制元件 & 實現無感知上拉載入更多
- iOS小技能:程式碼觸發button的點選事件、快速找到按鈕action方法
- iOS小技能:撥號、發郵件、簡訊、應用間跳轉
- iOS小技能:鏈式程式設計在iOS開發中的應用
- iOS小技能:iOS14 讀取使用者剪下板資料彈出提示的相容方案
- iOS小技能:因境外IP無法訪問導致 App 被拒的解決方案
- iOS小技能:RSA簽名、驗籤、加密、解密的原理
- iOS小技能:Xcode14新特性(適配)
- iOS小技能:Socket基礎知識
- iOS小技能:SKU檢視搭建
- iOS小技能: 日曆的使用(案例:兩個時間的比較、獲取最近30天的資料)
- iOS小技能:1. iOS 實現json資料提交 2. 對同一個URL的多次請求進行資料快取 3. 檢查網路狀態
- iOS小技能:使用正則表示式對聊天記錄的關鍵詞進行監控
- iOS小技能:去掉/新增導航欄黑邊(iOS13適配)