如何调试NSAllowsArbitraryLoads不工作?

时间:2015-12-02 07:59:23

标签: ios xcode ios9 app-transport-security

我在我的应用中的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文件实际上都包含应用程序的名称,这是正常的。我错了吗?

App Transport Security Settings Info.plist settings

2 个答案:

答案 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