【问题标题】:setDefaultCredential not working for UIWebView in iOS 7 but works fine in earlier iOS versionssetDefaultCredential 在 iOS 7 中不适用于 UIWebView,但在早期 iOS 版本中可以正常工作
【发布时间】:2013-09-08 06:14:55
【问题描述】:

我目前正在使用以下代码为 UIWebView 设置默认凭据。这在 iOS 6.1 及更早版本中运行良好。但是,在 iOS 7 Beta 6 中它根本不起作用。

我尝试加载的网页使用 Windows 身份验证。我可以在 iOS 7 的 Safari 中打开它们。但是,当我运行下面的代码,然后在 UIWebView 中打开 URL 时,我得到一个空的白色矩形并且什么都没有加载!就像我说的,这在 iOS 6.1 及更早版本中完美运行。

我还尝试了第二种方法,即使用 NSURLConnectionDelegate 传递凭据。第二种方法在 iOS 6.1 和更早版本中也可以正常工作,但在 iOS 7 中被破坏了。

有人知道为什么会这样吗?类似的经历?想法?

// Authenticate
NSURLCredential *credential = [NSURLCredential credentialWithUser:@"myusername"
                                                         password:@"mypassword"
                                                      persistence:NSURLCredentialPersistenceForSession];

NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
                                         initWithHost:@"mysite.com"
                                         port:80
                                         protocol:@"http"
                                         realm:nil
                                         authenticationMethod:NSURLAuthenticationMethodDefault];

[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];

【问题讨论】:

  • 您是否尝试过在 Apple 开发者论坛中询问有关 iOS7 的问题?
  • 是的 - 到目前为止没有回复
  • MPMoviePlayer 也有类似的问题

标签: iphone ios objective-c uiwebview


【解决方案1】:

我遇到了同样的问题 - 为 Windows 身份验证配置的 Sharepoint 站点的 NSURLConnection 在 iOS 6.1 中运行良好。在 iOS 7 中——无论我是针对 6 还是 7 构建应用程序——所有身份验证似乎都会成功(接收到正确的 cookie),但仍会以 401 响应;使用 cookie 发送的所有后续请求也会收到 401。

我通过转储 didReceiveAuthenticationChallenge 委托协议以支持 willSendRequestForAuthenticationChallenge 解决了这个问题。实现第二个委托协议意味着第一个永远不会被调用。

在你的委托中,实现这个委托协议:

- (void)connection:(NSURLConnection *)sender willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
   if ([challenge previousFailureCount] > 0]) {
       [[challenge sender] cancelAuthenticationChallenge:challenge];
   }else{
      NSURLCredential *credential = [NSURLCredential credentialWithUser:@"username" password:@"password" persistence:NSURLPersistenceForSession];
   [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
   }
}

在我心血来潮实现这个之后,我的 iOS 7 NTLM 身份验证问题就消失了。

【讨论】:

  • 我有一些类似但更复杂的东西,因为我需要多种不同的身份验证方式。身份验证在 iOS 6 或 7 中工作,但是当应用程序遇到一定数量的 NSURLConnections 时,这个更简单的块很有用。在我的情况下,我消耗了大量的网络服务,有些正在工作,有些没有,所以我在 didReceiveData 中得到了 401。奇怪的错误..似乎一旦您达到一定数量的连接,会话就会关闭并且服务器会丢失凭据。
  • 如果在使用 NSURLPersistenceForSession 时必须将其放入大量 willSendRequestForAuthenticationChallenge 中,这将导致服务器上出现大量连接池,并且在池耗尽之前您可能无法登录或获取数据..如果您必须多次这样做,请使用 NSURLPersistenceNone
【解决方案2】:

更新:此问题似乎将在 iOS 7.0.3 中修复

我在 Apple 开发者论坛上回答了这个问题,但现在 iOS7 已经过测试版了,我会在这里重新发布。目前 Windows 身份验证在 iOS7 中被破坏。我预计很快就会有解决方案,但在那之前,您可以通过在包含您的 UIWebView 的 UIViewController 中处理身份验证挑战来解决此问题。

基本上是你

  1. 自己创建一个 NSURLRequest 和 NSURLConnection
  2. 处理连接:didReceiveAuthenticationChallenge:
  3. 在连接中:didReceivedResponse 手动将数据加载到 UIWebView 中

下面我正在加载 PDF,但无论您的内容类型如何,该过程都一样。

//Make sure you implement NSURLConnectionDelegate and NSURLConnectionDataDelegate in your header

@interface MyViewController ()
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@property (strong, nonatomic) NSURLConnection *conn;
@property (strong, nonatomic) NSMutableData *pdfData;
@end

@implementation MyViewController 


//... all of your init and other standard UIViewController methods here...


//Method that loads UIWebview. You'll probably call this in viewDidLoad or somewhere similar... 
- (void) loadWebView {

    //Make Request manually with an NSURLConnection... 
    NSString *url = //Get your url
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    self.conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];

}

//#pragma mark - NSURLConnectionDelegate

//Handle authentication challenge (NSURLConnectionDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    if([challenge previousFailureCount] == 0) {

        NSString *username = //Get username
        NSString *password = //Get password

        //Use credentials to authenticate
        NSURLCredential *cred = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
        [[challenge sender] useCredential:cred forAuthenticationChallenge:challenge];

    } else {

        //Cancel authentication & connection
        [[challenge sender] cancelAuthenticationChallenge:challenge];
        [self.conn cancel];
        self.conn = nil;
    }
}

//#pragma mark - NSURLConnectionDataDelegate

//Received response (NSURLConnectionDataDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {

    //Init data
    self.pdfData = [NSMutableData data];
}

//Collect data as it comes in (NSURLConnectionDataDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.pdfData appendData:data];
}

//Handle connection failure (NSURLConnectionDataDelegate)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {

    //Clean up... 
    [self.conn cancel];
    self.conn = nil;
    self.pdfData = nil;

    //TODO: Notify user and offer next step...
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    //Finally, load data into UIWebview here (I'm loading a PDF)...
    [self.webView loadData:self.pdfData MIMEType:@"application/pdf" textEncodingName:@"utf-8" baseURL:nil];
}


@end

【讨论】:

  • Apple 让这些漏洞通过测试溜走是完全不能接受的(这已经是第二次发生了)。它使 iPad 在 Microsoft 企业环境中无法使用。
  • 感谢您提供此解决方案!但我猜它不适用于重定向?
  • @NLemay 重定向应该不是问题。如果您期望它们,您应该准备好处理它们。请参阅connection:didReceiveResponseconnection:willSendRequest:redirectResponse 方法here
  • 我尝试了完全相同,但由于某种原因它不起作用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多