即使蘋果已經(jīng)推遲ATS,但是也是早晚的事,此次就根據(jù)項目記錄項目中是怎么支持https自建證書的
-
后臺給到的證書是.crt格式的,但是項目需要的是der格式的(AFN3.0以上支持的是.der,3.0以下支持的是.cer)
轉(zhuǎn).der采用的命令行是:
openssl x509 -in /Users/nikkilin/Desktop/server.crt -out /Users/nikkilin/Desktop/server.der -outform DER
轉(zhuǎn).cer采用的命令行是:
openssl x509 -in /Users/nikkilin/Desktop/server.crt -out /Users/nikkilin/Desktop/server.cer -outform DER
- 接著將der證書拉入項目中
- 修改AFN網(wǎng)絡(luò)請求工具類
+ (instancetype)sharedTools {
static NetworkTools *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [NetworkTools new];
[instance initSessionManager];
});
return instance;
}
- (void)initSessionManager{
_sessionManager = [AFHTTPSessionManager manager];
_sessionManager.requestSerializer.timeoutInterval = 15;
_sessionManager.requestSerializer.cachePolicy = NSURLRequestUseProtocolCachePolicy;
_sessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"text/plain", @"*/*", nil];
AFImageDownloader *imageDownloader = [AFImageDownloader defaultInstance];
AFHTTPSessionManager *sessionManager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:nil];
sessionManager.responseSerializer = [AFImageResponseSerializer serializer];
imageDownloader.sessionManager = sessionManager;
[self setSecurityPolicyWithManager:_sessionManager];
[self setSecurityPolicyWithManager:sessionManager];
[UIButton setSharedImageDownloader:imageDownloader];
}
-(void) setSecurityPolicyWithManager:(AFHTTPSessionManager *)manager
{
AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
policy.allowInvalidCertificates = YES;// 是否允許自建證書或無效證書
policy.validatesDomainName = NO;
manager.securityPolicy = policy;
__weak AFHTTPSessionManager *weakManager = manager;
[manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession * _Nonnull session, NSURLAuthenticationChallenge * _Nonnull challenge, NSURLCredential *__autoreleasing _Nullable * _Nullable credential) {
SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
NSData *caData = [NSData dataWithContentsOfFile:cerPath];
weakManager.securityPolicy.pinnedCertificates = [NSSet setWithObject:caData];
SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caData);
NSArray *caArray = @[(__bridge id)(caRef)];
OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
SecTrustSetAnchorCertificatesOnly(serverTrust,NO);
if (errSecSuccess == status) {
NSCAssert(YES, @"SecTrustSetAnchorCertificates failed");
}
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if ([weakManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
//創(chuàng)建質(zhì)詢證書
NSURLCredential * credential = [NSURLCredential credentialForTrust:serverTrust];
if (credential) {
disposition = NSURLSessionAuthChallengeUseCredential;
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
//取消質(zhì)詢
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
}
}
return disposition;
}];
}
- 接著常用的第三方SDWebImage就加載不了https的圖片了,簡單粗暴的辦法就是
使用sd的這個方法,忽略證書,options設(shè)置SDWebImageAllowInvalidSSLCertificates
[self.imageV sd_setImageWithURL:[NSURL URLWithString:item.photo_source] placeholderImage:nil options:SDWebImageAllowInvalidSSLCertificates];
- 如果嫌每個地方都要添加options麻煩,那么可以給SDWebImage添加一個Category
@implementation SDWebImageDownloader (CXXSecurityValidate)
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler
{
SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"dev_merchant" ofType:@"cer"];
NSData *caData = [NSData dataWithContentsOfFile:cerPath];
SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caData);
NSArray *caArray = @[(__bridge id)(caRef)];
OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
SecTrustSetAnchorCertificatesOnly(serverTrust,NO);
if (errSecSuccess == status) {
NSCAssert(YES, @"SecTrustSetAnchorCertificates failed");
}
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
NSURLCredential * credential = [NSURLCredential credentialForTrust:serverTrust];
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if ([[NetworkTools sharedTools].sessionManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
if (credential) {
disposition = NSURLSessionAuthChallengeUseCredential;
} else {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
}
} else {
//取消質(zhì)詢
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
}
}
if (completionHandler) {
completionHandler(disposition, credential);
}
}
@end