【问题标题】:How to debug NSAllowsArbitraryLoads not working?如何调试 NSAllowsArbitraryLoads 不起作用?
【发布时间】:2016-03-06 09:16:36
【问题描述】:

我在我的应用程序的 UIWebView 中加载 youku.com 视频时遇到问题。我很确定这是由于应用程序传输安全性,因为用 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 执行此操作时的错误,对吗? (这不是一个信息量很大的错误!)

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

【问题讨论】:

  • 错误代码-999代表kCFURLErrorCancelled错误。

标签: ios xcode ios9 app-transport-security


【解决方案1】:

事实证明 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 实验,谢谢。请务必在工作时回复我。

【讨论】:

    【解决方案2】:

    请检查您的目标设置。您的 .plist 文件的名称必须在名为 Info.plist 文件的参数中的 Build Settings 的 Packaging 部分中。它必须是包含项目文件的文件夹中 .plist 文件的相对路径。

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

    这种情况有一种解决方案。在 UIWebView 开始从不受信任的 URL 加载请求之前,您必须使其受信任。 URL 加载系统缓存您的请求。当你以编程方式告诉它无论如何都要下载时,UIWebView 会从这个 URL 开始加载。

    这是我在项目中使用的代码sn-p:

    - (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
    

    【讨论】:

    • 啊,谢谢,这说明了这一点!我附上了一个屏幕截图,在我看来,我的设置似乎都是正确的。
    • 好吧,关于坏证书……这当然只是我的测试环境。我已经将证书导入模拟器。没有它,我根本无法加载任何数据。在我导入证书后它可以成功发出 AJAX 请求的事实表明这不是问题。此外,在查看具有有效证书的实时站点的实时版本的应用程序中也存在此问题。
    • 请注意,允许不受信任的网站会向任何黑客开放您的应用程序。特别是如果您从自己的自己的网站收到错误,那么解决方案是修复网站,而不是信任不受信任的网站。任何黑客都可以将请求从您的网站重定向到他们的网站,但他们无法伪造证书。通过信任不受信任的网站,他们不需要伪造任何东西。
    • 是的,实时站点有有效的凭据,当我让它工作时,我会适当地调整设置。但是,就目前而言,我根本无法影响应用程序传输安全性,而且我对这些设置中的任何一个都没有任何影响。首先我需要让它工作!
    • ...就是说。直到几个月前,似乎没有人认为 HTTPS 只是一种美好的东西,而且世界一直在转动。然后,Apple 几乎没有通知就决定现在必须关闭绝大多数网络?多年来,我一直在为我们的网站宣传 HTTPS,并且在这一年中我一直在逐步启用它。但是现在突然间我必须完成整个事情 RFN... 为什么?一大群人需要学会冷静,伙计。
    猜你喜欢
    • 2016-01-02
    • 2011-05-25
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2013-03-17
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    相关资源
    最近更新 更多