如何调试 NSAllowsArbitraryLoads 不工作?

How to debug NSAllowsArbitraryLoads not working?

我在应用的 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);
    }
}

目前我正在使用虚拟测试 URL 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做这个的时候报的错吧? (这不是一个非常有用的错误!)

另一件事,例如,就是你要编辑"Info.plist"这个文件。我没有这样的文件。我有 "ZaoMengShe-Info.plist"("ZaoMengShe" 是我的应用程序的名称)。但是 none 的问题显示了包含文件名的实际屏幕截图,所以据我所知,每个人的 Info.plist 文件实际上都包含应用程序的名称,这很正常。我错了吗?

请检查您的目标设置。您的 .plist 文件的名称必须位于名为 Info.plist 文件的参数中构建设置的打包部分。它必须是从包含项目文件的文件夹到 .plist 文件的相对路径。

更新: 您的错误消息包含 URL https://dev1.zaomengshe.com/c/54260 如果您从浏览器打开此 URL,您将看到它的 https 证书不受信任。所以取消你的请求不是因为应用程序传输安全,而是 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

事实证明,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 实验,谢谢。当它有效时一定要回复我。