iOS中集成HTTPS
證書是自簽名的HTTPS證書什燕,如果是CA認證的就不會有下面的事情了。項目組最后到阿里云去申請免費試用一年的HTTPS證書萍摊。下面的純屬是為了紀念曾經(jīng)折騰過的問題:
NSURLSession驗證HTTPS
首先要成為NSURLSession的代理
<pre>
NSString *urlString = @"https://xxxx";
NSURL *myUrl = [NSURL URLWithString:urlString];
NSMutableURLRequest *myRequest = [NSMutableURLRequest requestWithURL:myUrl cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0f];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:myRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
[task resume];
</pre>
然后實現(xiàn)下面的代理方法
<pre>
/*
- 代理方法 NSURLSessionDelegate
*/
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
NSLog(@"證書認證開始..");
//先導入證書
NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"你的證書名字" ofType:@"cer"]; //證書的路徑
NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(cerData));
NSArray * trustedCertificates = @[CFBridgingRelease(certificate)];
//1)獲取trust object
SecTrustRef trust = challenge.protectionSpace.serverTrust;
SecTrustResultType result;
//注意:這里將之前導入的證書設置成下面驗證的Trust Object的anchor certificate
SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)trustedCertificates);
//2)SecTrustEvaluate會查找前面SecTrustSetAnchorCertificates設置的證書或者系統(tǒng)默認提供的證書,對trust進行驗證
OSStatus status = SecTrustEvaluate(trust, &result);
if (status == errSecSuccess &&
(result == kSecTrustResultProceed ||
result == kSecTrustResultUnspecified)) {
NSLog(@"驗證成功..");
//3)驗證成功,生成NSURLCredential憑證cred恳邀,告知challenge的sender使用這個憑證來繼續(xù)連接
NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
[challenge.sender useCredential:cred forAuthenticationChallenge:challenge];completionHandler(NSURLSessionAuthChallengeUseCredential,cred);
} else {
NSLog(@"驗證失敗..");
[challenge.sender cancelAuthenticationChallenge:challenge];
}
}
</pre>
AFNetWorking
我們先封裝出來一個Post方法,設置AFN的setSecurityPolicy方法
<pre>
/**
- pots方法
*/
-
(void)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
// 1.獲得請求管理者
AFHTTPSessionManager *mgr = [[AFHTTPSessionManager manager] initWithBaseURL:[NSURL URLWithString:BaseUrl]];
// 2.申明返回的結(jié)果是text/html類型mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
// 加上這行代碼灶轰,https ssl 驗證谣沸。
[mgr setSecurityPolicy:[self customSecurityPolicy]];// 3.發(fā)送POST請求
[mgr POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * task, id responseObject) {
if (success) {
success(responseObject);
}
} failure:^(NSURLSessionDataTask * task, NSError * error) {
if (failure) {
failure(error);
}
}];
}
</pre>
自定義的customSecurityPolicy方法:
<pre>
-
(AFSecurityPolicy*)customSecurityPolicy
{
// /先導入證書
NSString *cerPath = [[NSBundle mainBundle] pathForResource:CertName ofType:@"cer"];//證書的路徑
NSData *certData = [NSData dataWithContentsOfFile:cerPath];// AFSSLPinningModeCertificate 使用證書驗證模式
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];// allowInvalidCertificates 是否允許無效證書(也就是自建的證書),默認為NO
// 如果是需要驗證自建證書笋颤,需要設置為YES
securityPolicy.allowInvalidCertificates = YES;//validatesDomainName 是否需要驗證域名乳附,默認為YES;
//假如證書的域名與你請求的域名不一致伴澄,需把該項設置為NO赋除;如設成NO的話,即服務器使用其他可信任機構頒發(fā)的證書非凌,也可以建立連接举农,這個非常危險,建議打開清焕。
//置為NO并蝗,主要用于這種情況:客戶端請求的是子域名,而證書上的是另外一個域名秸妥。因為SSL證書上的域名是獨立的,假如證書上注冊的域名是www.google.com沃粗,那么mail.google.com是無法驗證通過的粥惧;當然,有錢可以注冊通配符的域名*.google.com最盅,但這個還是比較貴的突雪。
//如置為NO起惕,建議自己添加對應域名的校驗邏輯。
securityPolicy.validatesDomainName = NO;NSSet *set = [[NSSet alloc] initWithObjects:certData, nil];
securityPolicy.pinnedCertificates = set;
return securityPolicy;
}
</pre>
完成咏删!