最近在做一个用AVplayer播放HTTPSURL,一直实现不了,最后用WKWebView实现的,但是需要证书的各种验证,这里把代码贴出来,以供大家参考。有什么不足的欢迎大家再补充。
双向验证:
- (void)webView:(WKWebView*)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge completionHandler:(void(^)(NSURLSessionAuthChallengeDispositiondisposition,NSURLCredential*_Nullablecredential))completionHandler{ NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
NSURLCredential*credential =nil;
// 服务器验证
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
// /* 调用自定义的验证过程 */
if([selfmyCustomValidation:challenge]) {
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
if(credential) {
disposition =NSURLSessionAuthChallengeUseCredential;
}
}else{
/* 无效的话,取消 */
disposition =NSURLSessionAuthChallengeCancelAuthenticationChallenge;
}
}else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate])
{//客户端认证
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRefinPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
SecIdentityRefidentity;
// 读取p12证书中的内容
OSStatusresult = [selfextractP12Data:inPKCS12DatatoIdentity:&identity];
if(result !=errSecSuccess){
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
return;
}
SecCertificateRefcertificate =NULL;
SecIdentityCopyCertificate(identity, &certificate);
constvoid*certs[] = {certificate};
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
credential = [NSURLCredential credentialWithIdentity:identity certificates:(NSArray*)CFBridgingRelease(certArray) persistence:NSURLCredentialPersistencePermanent];
if(credential) {
disposition =NSURLSessionAuthChallengeUseCredential;
}
}
if(completionHandler) {
completionHandler(disposition, credential);
}
}
-(OSStatus) extractP12Data:(CFDataRef)inP12Data toIdentity:(SecIdentityRef*)identity {
OSStatussecurityError =errSecSuccess;
CFStringRefpassword =CFSTR("123456");//证书密码
const void *keys[] = { kSecImportExportPassphrase };
constvoid*values[] = { password };
CFDictionaryRefoptions =CFDictionaryCreate(NULL, keys, values,1,NULL,NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError =SecPKCS12Import(inP12Data, options, &items);
if(securityError ==0) {
CFDictionaryRef ident = CFArrayGetValueAtIndex(items,0);
constvoid*tempIdentity =NULL;
tempIdentity =CFDictionaryGetValue(ident, kSecImportItemIdentity);
*identity = (SecIdentityRef)tempIdentity;
}
if(options) {
CFRelease(options);
}
returnsecurityError;
}
- (BOOL)myCustomValidation:(NSURLAuthenticationChallenge*)challenge
{
//获取trust object
SecTrustRef trust = challenge.protectionSpace.serverTrust;
SecTrustResultType result;
//导入证书
NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"serverShuang" ofType:@"der"];; //证书的路径
NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(cerData));
NSMutableArray*trustedCertificates = [NSMutableArraynew];
[trustedCertificatesaddObject:(__bridge_transferid)(certificate)];
// trustedCertificates = @[CFBridgingRelease(certificate)];
//注意:这里将之前导入的证书设置成下面验证的Trust Object的anchor certificate
SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)trustedCertificates);
//2)SecTrustEvaluate会查找前面SecTrustSetAnchorCertificates设置的证书或者系统默认提供的证书,对trust进行验证
OSStatusstatus =SecTrustEvaluate(trust, &result);
if(status ==errSecSuccess&&
(result ==kSecTrustResultProceed ||
result ==kSecTrustResultUnspecified)){//强制过
returnYES;
}
return NO;
}
单向验证:
- (void)webView:(WKWebView*)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge completionHandler:(void(^)(NSURLSessionAuthChallengeDispositiondisposition,NSURLCredential*_Nullablecredential))completionHandler{
//单向证书验证
// SecTrustRef servertrust = challenge.protectionSpace.serverTrust;
//
// SecCertificateRef certi= SecTrustGetCertificateAtIndex(servertrust, 0);
//
// NSData *certidata = CFBridgingRelease(CFBridgingRetain(CFBridgingRelease(SecCertificateCopyData(certi))));
//
// NSString *path = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"der"];
//
// 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(@"服务端认证失败");
//
// }
}
证书全部信任:
- (void)webView:(WKWebView*)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge completionHandler:(void(^)(NSURLSessionAuthChallengeDispositiondisposition,NSURLCredential*_Nullablecredential))completionHandler{
//全部信任
// if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
//
// NSURLCredential *credential = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
//
// completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
//
// }
}