玩了半年的Android和Java后端,最近又回来搞iOS了。 做开发本着能用最新就用最新的原则,所以战略放弃了NSURLConnection,改用NSURLSession。 而且苹果倡导使用https,并且这也是未来的趋势。所以就直接上了。 我们平时在访问https的网页时会出现证书过期啊、不受信任等问题,弹出一个对话框选择是否信任证书这样的情况。For example,12306某些页面打开因为是https,所以可能出现对话框说证书不信任。而GitHub虽然也是https,但是不会出现这样的问题。 那么我们在开发过程中,如果后端使用了私有的证书,也会出现这样的问题吧,如果不信任的话,不管是调用接口还是打开网页,都会失败。 那么如何去信任证书呢?
//
2程序自动安装证书的方式
NSURLSession *sesson = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:
[[NSOperationQueue alloc]init]];
首先我们要设置NSURLSession,添加代理方法。
NSURLSession * sesson =
[NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
注意:不能使用上面的这个方法,这样是进不去代理方法的!
然后在代理方法中实现对证书的操作 方法一:这是在开发者足够信任后端的安全的情况下做的,比如调个接口,这样做的结果就是忽略证书的验证,直接信任。
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){//服务器信任证书
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protection
Space.server
Trust];//服务器信任证书
if(completion
Handler)
completion
Handler(
NSURLSessionAuthChallengeUseCredential,credential);
}
}
方法二:可以把证书加到工程中,然后https访问时在代理方法中进行证书的验证
- (
void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(
void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
SecTrustRef servertrust = challenge
.protectionSpace.serverTrust;
SecCertificateRef certi= SecTrustGetCertificateAtIndex(servertrust,
0);
NSData *certidata = CFBridgingRelease(CFBridgingRetain(CFBridgingRelease(SecCertificateCopyData(certi))));
NSString *path = [[
NSBundle mainBundle] pathForResource:@
"https" ofType:@
"cer"];
NSData *localCertiData = [NSData dataWithContentsOfFile:path];
if ([certidata isEqualToData:localCertiData]) {
NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:servertrust];
[challenge
.sender useCredential:credential forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
NSLog(@
"服务端证书认证通过");
}
else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,
nil);
NSLog(@
"服务端认证失败");
}
}
OK,这样就可以访问https的接口、网页了。
- (void)getWithUrlString:(NSString *)f_str_url NSString:(NSString *)f_aTC_String success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock{
NSMutableString * t_aTC_mutableUrl =
[[NSMutableString alloc] initWithString:f_str_url];
[t_aTC_mutableUrl appendString:f_aTC_String];
NSLog(@"url %@",t_aTC_mutableUrl);
NSURL * t_aTC_URL =[NSURL URLWithString:[t_aTC_mutableUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
NSURLRequest * t_aTC_urlRequest = [NSURLRequest requestWithURL:t_aTC_URL];
//
2程序自动安装证书的方式
NSURLSession *sesson = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:
[[NSOperationQueue alloc]init]];
NSURLSessionDataTask * t_aTC_dataTask = [sesson dataTaskWithRequest:t_aTC_urlRequest completionHandler:^(NSData * _Nullable t_aTC_data, NSURLResponse * _Nullable t_aTC_response, NSError * _Nullable t_aTC_error) {
if (t_aTC_error) {
failureBlock(t_aTC_error);
}
else {
NSString * t_str_result =
[[NSString alloc] initWithData:t_aTC_data encoding:NSUTF8StringEncoding];
successBlock(t_str_result);
}
}];
[t_aTC_dataTask resume];
}
- (
void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(
void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
if([challenge
.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge
.protectionSpace.serverTrust];
if(completionHandler)
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
}
SecTrustRef servertrust = challenge
.protectionSpace.serverTrust;
SecCertificateRef certi= SecTrustGetCertificateAtIndex(servertrust,
0);
NSData *certidata = CFBridgingRelease(CFBridgingRetain(CFBridgingRelease(SecCertificateCopyData(certi))));
NSString *path = [[
NSBundle mainBundle] pathForResource:@
"https" ofType:@
"cer"];
NSData *localCertiData = [NSData dataWithContentsOfFile:path];
if ([certidata isEqualToData:localCertiData]) {
NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:servertrust];
[challenge
.sender useCredential:credential forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
NSLog(@
"服务端证书认证通过");
}
else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,
nil);
NSLog(@
"服务端认证失败");
}
}