ios使用WKWebView进行双向认证的实现

在iOS开发中,使用WKWebView加载网页时可能会遇到需要进行身份认证的情况,该代码通过处理webView:didReceiveAuthenticationChallenge:completionHandler:方法来处理认证挑战。

首先,根据认证挑战的类型,判断是客户端认证还是服务器信任认证。如果是客户端认证,则从本地获取证书文件(.p12格式),将证书信息提取出来创建NSURLCredential对象,并将其传递给completionHandler回调函数。如果是服务器信任认证,则直接创建NSURLCredential对象,并将其传递给completionHandler回调函数。
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSLog(@"\n双向认证方式didReceiveAuthenticationChallenge:%@", challenge.protectionSpace.authenticationMethod);
    
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) {
        // 客户端认证,这里携带证书
        SecTrustRef trust = NULL;
        SecIdentityRef identity = NULL;
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSArray *fileList = [[[NSFileManager defaultManager] contentsOfDirectoryAtPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] error:nil]
                             pathsMatchingExtensions:[NSArray arrayWithObject:@"p12"]];
        NSString *certPath1 = [NSString stringWithFormat:@"%@/%@",[paths objectAtIndex:0],[fileList objectAtIndex:0]];

        if(!certPath1) {
            NSLog(@"client.p12:not exist");
            NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
            return;
        }

        NSData *PKCS12Data = [NSData dataWithContentsOfFile:certPath1];

        if ([self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data]) {
            SecCertificateRef certificate = NULL;
            SecIdentityCopyCertificate(identity, &certificate);
            const void*certs[] = {certificate};
            CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL);
            NSURLCredential *credential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge  NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
            completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
        }else{
            completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
        }
    } else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
    } else {
        completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
    }
    
         
    
}
在evaluateServerTrust:forDomain:方法中,根据指定的域名创建证书校验策略,并绑定到服务器的证书上。然后通过SecTrustEvaluate方法评估当前的serverTrust是否可信任。
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain {
    domain = nil;
    /*
     * 创建证书校验策略
     */
    NSMutableArray *policies = [NSMutableArray array];
    if (domain) {
        [policies addObject:(__bridge_transfer id) SecPolicyCreateSSL(true, (__bridge CFStringRef) domain)];
    } else {
        [policies addObject:(__bridge_transfer id) SecPolicyCreateBasicX509()];
    }

    // 绑定校验策略到服务端的证书上
    SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef) policies);

    // 评估当前serverTrust是否可信任
    SecTrustResultType result;
    SecTrustEvaluate(serverTrust, &result);
    if (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed) {
        return YES;
    }
    return NO;
}
extractIdentity:andTrust:fromPKCS12Data:方法用于从PKCS12格式的数据中提取身份和信任对象。
- (BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {
    OSStatus securityError = errSecSuccess;

    NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"123456" forKey:(__bridge id)kSecImportExportPassphrase];

    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    securityError = SecPKCS12Import((__bridge CFDataRef)inPKCS12Data,(__bridge CFDictionaryRef)optionsDictionary,&items);

    if(securityError == 0) {
        CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
        const void*tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
        *outIdentity = (SecIdentityRef)tempIdentity;
        const void*tempTrust =NULL;
        tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
        *outTrust = (SecTrustRef)tempTrust;
    } else {
        NSLog(@"Failedwith error code %d",(int)securityError);
        return NO;
    }
    return YES;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
检测iOSWKWebView白屏问题的方法有以下几种: 1. 检查网络连接:首先要确保设备处于正常的网络环境下。白屏问题有可能是由于网络连接不稳定或断开导致的,可以通过尝试打开其他网页或应用来测试网络连接是否正常。 2. 检查网页URL:检查加载的网页URL是否正确。有时候白屏问题是由于URL输入错误或者失效导致的,可以尝试通过其他方式打开相同的URL来检查是否能够正常加载网页。 3. 检查代理设置:如果设备上启用了代理服务器,可能会干扰WKWebView的正常加载。可以在系统设置中检查代理设置是否正确或者尝试禁用代理来解决问题。 4. 清除缓存和Cookie:有时候缓存或者Cookie的问题会导致WKWebView白屏。可以尝试清除应用的缓存和Cookie来解决问题。可以通过从系统设置中找到当前应用,然后选择清除缓存和Cookie来进行操作。 5. 检查WebView配置:在创建WKWebView实例时,可以通过配置参数来定制WebView的行为。检查WebView的配置是否正确,比如是否启用了JavaScript执行以及是否设置了正确的User Agent等。 6. 检查网页内容:有时候网页内部的错误会导致WKWebView无法正常加载并显示内容。可以尝试在其他设备或者浏览器上加载同一网页,检查是否有错误提示或者加载失败的情况。 通过以上的方法可以尝试解决iOSWKWebView白屏问题,如果问题仍然存在,可能需要进一步排查代码逻辑或者咨询相关开发者或技术支持人员的帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值