我在我的应用中的UIWebView中加载youku.com视频时遇到问题。我很确定它是由App Transport Security引起的,因为用HTTPS URL替换嵌入工作正常。当然,没有HTTPS等效URL,因为中国。
我已经了解了各种NSAppTransportSecurity设置。我的第一直觉当然是尝试NSAllowsArbitraryLoads来至少验证问题,但这不起作用。然后我跟踪了各种在线指南,这些指南展示了你应该如何使用NSExceptionDomains,但这也不起作用。
现在我被卡住了。 FWIW,我正在捕获这样的URL加载错误:
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
...
if (error.code == NSURLErrorCancelled)
{
NSLog(@"NSURLErrorCancelled: URL %@ error %@", urlString, error);
}
}
目前我正在使用虚拟测试网址exon.name,这会产生:
2015-12-02 15:47:22.312 ZaoMengShe[81707:903426] NSURLErrorCancelled: URL https://dev1.zaomengshe.com/c/54260 error Error Domain=NSURLErrorDomain Code=-999 "(null)" UserInfo={NSErrorFailingURLKey=http://exon.name/, NSErrorFailingURLStringKey=http://exon.name/}
要确认,-999是App Transport Security执行此操作时的错误,对吗? (这不是一个非常有用的错误!)
另一件事,如在例如NSAllowsArbitraryLoads not working,您必须编辑" Info.plist"文件。我没有这样的档案。我有" ZaoMengShe-Info.plist" (" ZaoMengShe"是我的应用程序的名称)。但是没有一个问题显示包含文件名的实际屏幕截图,所以我知道每个人的Info.plist文件实际上都包含应用程序的名称,这是正常的。我错了吗?
答案 0 :(得分:2)
事实证明,NSAllowsArbitraryLoads在这种情况下工作正常。我的问题是我遇到了另一个限制。在新的安全策略中,您不允许在安全(HTTPS)页面中加载不安全(HTTP)活动内容。这在浏览器和UIWebView中都是如此。似乎没有办法解决此问题。
这里有一些额外的日志来显示关闭然后再打开NSAllowsArbitraryLoads的错误消息。它无论如何都会失败,但在第一种情况下我收到了额外的错误消息:
2015-12-07 17:58:10.589 TestWeb[13583:4566542] about to load url https://dev1.zaomengshe.com/c/54260
2015-12-07 17:58:15.966 TestWeb[13583:4569606] App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
2015-12-07 17:58:16.045 TestWeb[13583:4566542] failed to load
2015-12-07 17:58:40.879 TestWeb[13583:4566542] NSURLErrorCancelled: error Error Domain=NSURLErrorDomain Code=-999 "(null)" UserInfo={NSErrorFailingURLKey=http://exon.name/, NSErrorFailingURLStringKey=http://exon.name/}
2015-12-07 17:58:40.895 TestWeb[13583:4569023] void SendDelegateMessage(NSInvocation *): delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
2015-12-07 17:58:41.878 TestWeb[13583:4569606] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
2015-12-07 17:58:41.884 TestWeb[13583:4566542] finished load urlString: https://dev1.zaomengshe.com/c/54260
2015-12-07 17:54:57.431 TestWeb[13503:4532874] about to load url https://dev1.zaomengshe.com/c/54260
2015-12-07 17:55:02.339 TestWeb[13503:4532874] failed to load
2015-12-07 17:55:15.310 TestWeb[13503:4532874] NSURLErrorCancelled: error Error Domain=NSURLErrorDomain Code=-999 "(null)" UserInfo={NSErrorFailingURLKey=http://exon.name/, NSErrorFailingURLStringKey=http://exon.name/}
2015-12-07 17:55:15.313 TestWeb[13503:4533886] void SendDelegateMessage(NSInvocation *): delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
2015-12-07 17:55:16.210 TestWeb[13503:4534307] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9843)
2015-12-07 17:55:16.653 TestWeb[13503:4532874] finished load urlString: https://dev1.zaomengshe.com/c/54260
在我的情况下,我在iframe中加载了一个不安全的优酷视频,iframe计为活动内容。因此,它无法使其发挥作用。优酷不提供HTTPS内容。
解决方案结果非常简单:将整个应用程序移回我的网站的HTTP版本并保留NSAllowsArbitraryLoads标志。万岁!这是一个有趣的HTTPS实验实验,谢谢你。确保在工作时回复我。
答案 1 :(得分:0)
请检查您的目标设置。 .plist文件的名称必须位于参数Info.plist文件中的Build Settings的Packaging部分中。它必须是包含项目文件的文件夹中.plist文件的相对路径。
更新: 您的错误消息包含网址https://dev1.zaomengshe.com/c/54260 如果您从浏览器打开此URL,您将看到它的https证书不受信任。因此取消您的请求不是因为App Transport Security,而是UIWebView不受信任的证书安全性。
这种情况有一种解决方案。在UIWebView开始从不受信任的URL加载请求之前,您必须使其受信任。 URL加载系统缓存您的请求。当你以编程方式告诉它下载时,UIWebView开始从这个URL加载。
以下是我在项目中使用的代码段:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
if([request.URL.scheme isEqualToString:@"https"] && ![request.URL.absoluteString hasPrefix:[AppData sharedInstance].serverBaseUrl] && ![self.authenticatedUrls containsObject:request.URL.absoluteString]){
__weak NBTransferFromCardConfirmationVC * weakself = self;
NBInsecureSslAuth * auth=[NBInsecureSslAuth new];
[auth authInsecureUrlRequet:request
success:^{
[weakself.authenticatedUrls addObject:request.URL.absoluteString];
[webView loadRequest:request];
} failure:^(NSError *error) {
[weakself.authenticatedUrls addObject:request.URL.absoluteString];
[webView loadRequest:request];
// showErrorWithTitle(@"Error", error.localizedDescription);
}];
return NO;
}else{
return YES;
}
}
NBInsecureSslAuth的源代码:
@implementation NBInsecureSslAuth
- (void)authInsecureUrlRequet:(NSURLRequest*)request success:(void (^)(void))success failure:(void (^)(NSError * error))failure{
AFHTTPClient* client = [[AFHTTPClient alloc] initWithBaseURL:request.URL];
client.allowsInvalidSSLCertificate=YES;
[client setDefaultHeader:@"User-Agent" value:[NSString stringWithFormat:@"%@/%@ (iOS %@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]]];
NSMutableURLRequest * authRequest=[client requestWithMethod:request.HTTPMethod path:@"" parameters:nil];
AFHTTPRequestOperation * operation=
[client HTTPRequestOperationWithRequest:authRequest
success:^(AFHTTPRequestOperation *operation, id responseObject) {
if(success){
success();
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if(failure){
failure(error);
}
}];
[client enqueueHTTPRequestOperation:operation];
}
@end