原文地址 https://lm1024.xyz/archives/34
看了这篇有关对 iOS app 进行安全加固看到防止http抓包后感觉自己能做一下实验。
分析
1、项目中能用到网络请求的地方一般都为调API接口、上传文件、加载文件、拉取图片几种情况。
2、第三方依赖库基础 AFNetwork SDWebImage。
3、第三方库源码分析。
- AFNetworking
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
self = [super init];
if (!self) {
return nil;
}
if (!configuration) {
configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
}
self.sessionConfiguration = configuration;
self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = 1;
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
self.responseSerializer = [AFJSONResponseSerializer serializer];
self.securityPolicy = [AFSecurityPolicy defaultPolicy];
#if !TARGET_OS_WATCH
self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif
self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];
self.lock = [[NSLock alloc] init];
self.lock.name = AFURLSessionManagerLockName;
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
for (NSURLSessionDataTask *task in dataTasks) {
[self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
}
for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
[self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
}
for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
[self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
}
}];
return self;
}
从这段代码中我们可以看出AFNetworking
所有的session
的产生都是self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
这行代码负责产生
- SDWebImage
SDWebImage负责将网络图片下载到本地并缓存的功能,那么我们只需要分析下载器相关的部分代码,从SDWebImageDownloader
- (void)createNewSessionWithConfiguration:(NSURLSessionConfiguration *)sessionConfiguration {
[self cancelAllDownloads];
if (self.session) {
[self.session invalidateAndCancel];
}
sessionConfiguration.timeoutIntervalForRequest = self.downloadTimeout;
/**
* Create the session for this task
* We send nil as delegate queue so that the session creates a serial operation queue for performing all delegate
* method calls and completion handler calls.
*/
self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
delegate:self
delegateQueue:nil];
}
从这段代码中能看出session
也是由self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
这行代码产生。
解决方案
(1)只针对AFNetwork
我们可以有
1、继承AFHTTPSessionManager
在子类中重写- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration
方法
2、hook - (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration
方法
3、hook + (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;
系统方法
(2)只针对SDWebImageView
我们有
1、SDWebImageDownloader
是一个单例,那么我们可以 直接设置[SDWebImageDownloader sharedDownloader].sessionConfiguration.connectionProxyDictionary = @{}
2、hook - (void)createNewSessionWithConfiguration:(NSURLSessionConfiguration *)sessionConfiguration
3、hook + (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;
系统方法
基于上面的情况和项目整体考虑采用了 + (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;
系统方法
源码
#import "NSURLSession+PLCategory.h"
#import <objc/runtime.h>
void swizzing(Class class, SEL originalSelector, SEL swizzledSelector)
{
Method originalMethod = class_getClassMethod(class, originalSelector);
Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
@implementation NSURLSession (QYCategory)
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [NSURLSession class];
swizzing(class, @selector(sessionWithConfiguration:), @selector(qy_sessionWithConfiguration:));
swizzing(class, @selector(sessionWithConfiguration:delegate:delegateQueue:),
@selector(qy_sessionWithConfiguration:delegate:delegateQueue:));
});
}
+ (NSURLSession *)qy_sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
delegate:(nullable id<NSURLSessionDelegate>)delegate
delegateQueue:(nullable NSOperationQueue *)queue
{
if (!configuration)
{
configuration = [[NSURLSessionConfiguration alloc] init];
}
configuration.connectionProxyDictionary = @{};
return [self qy_sessionWithConfiguration:configuration delegate:delegate delegateQueue:queue];
}
+ (NSURLSession *)qy_sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
{
if (configuration)
{
configuration.connectionProxyDictionary = @{};
}
return [self qy_sessionWithConfiguration:configuration];
}
@end