iOS 16、Xcode14.2下WKWebView允许未验证SSL证书问题求助
解决iOS 16下WKWebView加载自签名HTTPS证书失败(代理方法未触发)的开发阶段方案
针对你遇到的问题,给你几个开发阶段可用的排查和解决步骤,均无需适配App Store:
1. 补全ATS配置,别只设Allow Arbitrary Loads
iOS 10+之后,WKWebView的ATS有单独配置项,仅开启Allow Arbitrary Loads可能不满足要求。在Info.plist中添加以下完整配置:
<key>NSAppTransportSecurity</key> <dict> <key>Allow Arbitrary Loads</key> <true/> <key>Allow Arbitrary Loads in Web Content</key> <true/> <!-- 若明确测试域名,可添加精准例外配置 --> <key>NSExceptionDomains</key> <dict> <key>你的测试域名</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> <key>NSExceptionRequiresForwardSecrecy</key> <false/> </dict> </dict> </dict>
2. 确认navigationDelegate的设置时机
必须在WKWebView初始化完成后、调用loadRequest之前设置代理,示例代码:
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; // 先设置代理,再加载请求 self.webView.navigationDelegate = self; [self.view addSubview:self.webView]; [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"你的HTTPS测试链接"]]];
如果先执行loadRequest再设置代理,代理方法必然不会触发。
3. 检查代理方法签名与逻辑
OC方法签名不能有任何错误,建议修改为带类型判断的版本(确保仅处理服务器证书验证挑战):
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler { // 仅处理服务器证书验证类型的挑战 if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential, credential); } else { // 其他类型挑战按默认逻辑处理 completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } }
同时确保你的ViewController已正确遵守WKNavigationDelegate协议。
4. 兜底方案:用NSURLProtocol拦截请求手动处理证书
如果上述方法均无效,可通过NSURLProtocol拦截WKWebView请求,自行接管证书验证流程:
步骤1:注册自定义Protocol
在AppDelegate的application:didFinishLaunchingWithOptions:中添加:
[NSURLProtocol registerClass:[CustomURLProtocol class]];
步骤2:实现CustomURLProtocol类
#import <Foundation/Foundation.h> @interface CustomURLProtocol : NSURLProtocol @end @implementation CustomURLProtocol { NSURLSessionDataTask *_task; } + (BOOL)canInitWithRequest:(NSURLRequest *)request { // 仅拦截指定测试域名的HTTPS请求 if ([request.URL.scheme isEqualToString:@"https"] && [request.URL.host containsString:@"你的测试域名"]) { return ![NSURLProtocol propertyForKey:@"HandledByCustomProtocol" inRequest:request]; } return NO; } + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return request; } - (void)startLoading { NSMutableURLRequest *mutableRequest = [self.request mutableCopy]; [NSURLProtocol setProperty:@YES forKey:@"HandledByCustomProtocol" inRequest:mutableRequest]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]]; _task = [session dataTaskWithRequest:mutableRequest]; [_task resume]; } - (void)stopLoading { [_task cancel]; } #pragma mark - NSURLSessionDelegate - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential, credential); } else { completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } } #pragma mark - NSURLSessionDataDelegate - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; completionHandler(NSURLSessionResponseAllow); } - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { [self.client URLProtocol:self didLoadData:data]; } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if (error) { [self.client URLProtocol:self didFailWithError:error]; } else { [self.client URLProtocolDidFinishLoading:self]; } } @end
该方案通过接管请求流程,强制触发证书验证逻辑,可解决WKWebView自带验证不回调的问题。
内容的提问来源于stack exchange,提问作者user1664018
相关产品推荐
相关产品推荐

