最近在做Safencrypt安全项目,其实就是对网络请求的数据进行报文级别的加密。为了简化SDK的使用,决定使用NSURLProtocol来自动监听HTTP请求并加密解密。
通过[NSURLProtocol registerClass: [NetworkInject class]];
注入了自定义的NSURLProtocol类,在测试直接通过[NSURLSession sharedSession]
进行的请求是没问题的,可以拦截到;但是为了更贴近实际,在Demo中使用AFN3.0进行了网络请求,发现并没有拦截成功。经过一番研究发现AFN中是通过
sessionWithConfiguration:delegate:delegateQueue:
这个方法得到的session,这样得到的session我们监听不到是因为NSURLSessionConfiguration。我们进到NSURLSessionConfiguration里面看一下,他有一个属性@property (nullable, copy) NSArray<Class> *protocolClasses;
这是一个NSURLProtocol数组,我们监控网络是通过注册NSURLProtocol来进行网络监控的,但是通过 sessionWithConfiguration:delegate:delegateQueue:
得到的session,他的configuration中已经有一个NSURLProtocol,所以他不会使用我们的NSURLProtocol。
找到了问题我们开始解决,我们将NSURLSessionConfiguration的属性protocolClasses的get函数替换掉,换成我们自己的函数,返回我们自己的protocol,这样,我们就能够监控到通过 sessionWithConfiguration:delegate:delegateQueue:
得到的session的网络请求,方法如下,在正常我们注册NSURLProtocol的类里面添加如下两个方法,然后调用+ (void)injectNSURLSessionConfiguration
这个方法即可。
+ (void)injectNSURLSessionConfiguration{
Class cls = NSClassFromString(@"__NSCFURLSessionConfiguration") ?: NSClassFromString(@"NSURLSessionConfiguration");
Method originalMethod = class_getInstanceMethod(cls, @selector(protocolClasses));
Method stubMethod = class_getInstanceMethod([self class], @selector(protocolClasses));
if (!originalMethod || !stubMethod) {
[NSException raise:NSInternalInconsistencyException format:@"Couldn't load NEURLSessionConfiguration."];
}
method_exchangeImplementations(originalMethod, stubMethod);
}
- (NSArray *)protocolClasses {
return @[[NetworkInject class]];
}
最后实现的效果图截图
参考文章:https://www.aliyun.com/jiaocheng/359256.html,感谢原作者提供的思路
网友评论