SDWebImage无SSL证书时操作被取消,能否不改库禁用证书验证?
解决SDWebImage加载HTTPS图片时的证书验证问题
嘿,这个问题我之前帮好几个开发者处理过!SDWebImage对SSL证书的验证确实比Safari严格不少——Safari即使你取消了证书弹窗还能加载图片,是因为它有一套容错机制,但SDWebImage默认会直接终止不符合验证要求的请求。不过放心,完全不用修改SDWebImage的源码,就能通过配置跳过证书验证,下面给你两种实用的方案:
方案一:全局禁用证书验证(适合所有图片请求)
你可以自定义一个URL协议处理类,替换SDWebImage默认的网络会话配置,让所有HTTPS请求都跳过证书验证:
首先创建一个自定义的CustomURLProtocol类:
#import <Foundation/Foundation.h> @interface CustomURLProtocol : NSURLProtocol @end @implementation CustomURLProtocol + (BOOL)canInitWithRequest:(NSURLRequest *)request { // 只拦截HTTPS请求,避免重复处理 return [[request.URL scheme] isEqualToString:@"https"] && ![NSURLProtocol propertyForKey:@"HandledByCustomURLProtocol" inRequest:request]; } + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return request; } - (void)startLoading { NSMutableURLRequest *mutableRequest = [self.request mutableCopy]; [NSURLProtocol setProperty:@YES forKey:@"HandledByCustomURLProtocol" inRequest:mutableRequest]; NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; self.task = [session dataTaskWithRequest:mutableRequest]; [self.task resume]; } - (void)stopLoading { [self.task cancel]; } #pragma mark - NSURLSessionDelegate - (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]; completionHandler(NSURLSessionAuthChallengeUseCredential, credential); return; } // 其他验证类型按默认逻辑处理 completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } @end
然后在App启动时(比如AppDelegate的didFinishLaunchingWithOptions里)配置SDWebImage使用这个自定义协议:
// 创建自定义会话配置 NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; sessionConfig.protocolClasses = @[[CustomURLProtocol class]]; // 替换SDWebImage的全局管理器 SDWebImageManager *customManager = [[SDWebImageManager alloc] initWithCache:[SDImageCache sharedImageCache] downloader:[[SDWebImageDownloader alloc] initWithSessionConfiguration:sessionConfig]]; [SDWebImageManager setSharedManager:customManager];
方案二:仅针对单个请求跳过验证(更安全)
如果不想全局放开验证,只想给特定的图片请求跳过证书检查,可以在加载图片时传入自定义的下载器:
// 创建自定义下载器并设置代理 SDWebImageDownloader *customDownloader = [[SDWebImageDownloader alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; customDownloader.delegate = self; // 加载图片时使用这个下载器 [self.imageView sd_setImageWithURL:[NSURL URLWithString:@"你的图片URL"] placeholderImage:nil options:0 context:@{SDWebImageContextDownloader : customDownloader}];
然后实现SDWebImageDownloaderDelegate方法来处理证书验证:
- (void)downloader:(SDWebImageDownloader *)downloader didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { // 信任当前请求的服务器证书 NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential, credential); return; } completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); }
必须提醒的安全注意事项
⚠️ 划重点! 禁用SSL证书验证会让你的App面临中间人攻击的风险,黑客可以窃取或篡改图片请求的数据。所以这个方案只适合测试环境临时使用,正式上线的App一定要配置合法的SSL证书,或者采用「证书锁定(Certificate Pinning)」的方式来保障安全——SDWebImage也支持证书锁定,感兴趣的话可以去看它的官方文档。
内容的提问来源于stack exchange,提问作者Severyn Katolyk
相关产品推荐
相关产品推荐

