iOS NSURLSession Https请求

玩了半年的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.protectionSpace.serverTrust];//服务器信任证书
        if(completionHandler)
            completionHandler(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(@"服务端认证失败");
    }

}

猜你喜欢

转载自blog.csdn.net/u012138272/article/details/76714099