引言
今天用户Naruto反馈之前的demo:https://download.csdn.net/download/u011018979/16768533有点复杂,因为他的需求是只要拖入我自定义的NSURLProtocol子类到动态库,就可以自动拦截http请求。
针对他的要求,今天特意写了一个简单的demo。
其实就是由原来的手动注册我们的协议类,使用了小技巧,采用分类的形式在load方法进行自动注册而已目前demo是只要加载NSURL类就会自动注入我自定义NSURLProtocol子类进行http 拦截,当然你也可以更换到其他分类,不一定是NSURL(只要是你觉得会触发的类都行)
本文demo下载地址https://download.csdn.net/download/u011018979/16840774
I、原理
1、基于NSURLProtocol拦截请求:
HTTP 请求开始时,URL 加载系统创建一个合适的 NSURLProtocol 对象处理对应的 URL 请求,因此我们只需写一个继承自 NSURLProtocol 的类,并通过 - registerClass: 方法注册我们的协议类,然后 URL 加载系统就会在请求发出时使用我们创建的协议对象对该请求进行处理。
2、采用分类的形式在load方法进行自动注册协议类
II、基于NSURLProtocol拦截http请求
- 自定义NSURLProtocol子类
- 对[KNURLProtocol shareInstance].requestBlock =进行赋值;因为拦截的请求会交给requestBlockForRequst处理;可在这个block打印请求信息进行调试验证
- 注册协议类:
方式一:在app启动的时候调用KNURLProtocol的addRequestBlock方法进行 方式二:采用分类的形式在load方法进行自动注册协议类(针对动态库/静态库项目)
2.1、采用分类的形式在load方法进行自动注册协议类
#import "NSURL+registerURLProtocolClass.h" @implementation NSURL (registerURLProtocolClass) +(void)load{ [super load]; [self requestBlock]; } #pragma mark 拦截全局请求 + (void)requestBlock{ [KNURLProtocol handleRequest:^NSURLRequest *(NSURLRequest *request) { NSLog(@"拦截到请求-%@",request); dispatch_async(dispatch_get_main_queue(), ^{ // self.blockTv.text = [self.blockTv.text stringByAppendingString:[NSString stringWithFormat:@"拦截到请求--%@\n",request]]; }); return request; }]; }
2.2、 自定义NSURLProtocol子类
- 核心方法
/** 决定请求是否需要当前协议对象处理 问:是自动拦截? 答:是,你可以自己写个开关 或者自己定义拦截规则 目前demo只是判断是URL 就进行拦截 (isUrl) 协议类的注册,可采用分类的形式在load方法进行自动注册 */ +(BOOL)canInitWithRequest:(NSURLRequest *)request{ if ([NSURLProtocol propertyForKey:protocolKey inRequest:request]) { return NO; } NSString * url = request.URL.absoluteString; return [self isUrl:url]; } /** 对当前的请求对象需要进行哪些处理 */ +(NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return [[KNURLProtocol shareInstance] requestBlockForRequst:request]; } -(NSURLRequest *)requestBlockForRequst:(NSURLRequest *)request{ if(self.requestBlock){ return self.requestBlock(request); }else{ return request; } }
- KNURLProtocol.h
// // KNURLProtocol.h // KNURLProtocolDemo // // Created by mac on 2021/4/19. // #import <Foundation/Foundation.h> #import "HSSingleton.h" typedef NSURLRequest *(^requestBlock) (NSURLRequest *request); NS_ASSUME_NONNULL_BEGIN @interface KNURLProtocol : NSURLProtocol @property (nonatomic, copy) NSURLRequest *(^requestBlock)(NSURLRequest *request); HSSingletonH(Instance); /** 拦截全局请求 @param block 请求回调,block返回修改后的请求 */ +(void)handleRequest:(requestBlock)block; /** 禁止所有网络请求 */ +(void)cancelAllRequest; /** 恢复所有网络请求 */ +(void)resumeAllRequest; @end NS_ASSUME_NONNULL_END
- KNURLProtocol.m
see also
- 创建分类的入口
- 之前的demo请看这篇文章:https://kunnan.blog.csdn.net/article/details/115690756
从CSDN下载demo资源:https://download.csdn.net/download/u011018979/167685331、文章:https://kunnan.blog.csdn.net/article/details/115690756 2、应用场景:2.1、 自定义请求头的HTTPHeaderField 2.2、针对NSURLSessionConfiguration设置代理IP和端口,让一些特殊的请求走自定义的隧道IP和端口 2.3、对网络请求的数据进行报文级别的加密:使用NSURLProtocol来自动监听HTTP请求并加密解密。通过[NSURLProtocol registerClass: [NetworkInject class]];注入了自定义的NSURLProtocol类 3、原理:利用NSURLProtocol 拦截 HTTP 请求 基于NSURLProtocol实现iOS应用底层所有网络请求拦截(含网页ajax请求拦截【不支持WKWebView】);HTTP 请求开始时,URL 加载系统创建一个合适的 NSURLProtocol 对象处理对应的 URL 请求,因此我们只需写一个继承自 NSURLProtocol 的类,并通过 - registerClass: 方法注册我们的协议类,然后 URL 加载系统就会在请求发出时使用我们创建的协议对象对该请求进行处理。4、特色功能:4.1http-dns防止DNS劫持。会直接从本地或特定服务器地址进行DNS解析,是一种避免DNS劫持的措施 https://kunnan.blog.csdn.net/article/details/115868333
4.2 禁止网络代理抓包(开启后使用代理方式抓包的程序无法抓到此App中的请求,且计时处于代理网络下也不会影响App本身的请求)https://kunnan.blog.csdn.net/article/details/115866030




