2016-07-22 103 views
2

我一直在试图设置一个web视图包装应用程序,它将加载一个网站的内容(还有待启动)。目前,该网站处于开发模式,并且网站的唯一端点受到http身份验证的保护。Swift - WebView HTTP验证 - 最干净的解决方案

我一直在寻找这种解决方案:Swift webview xcode post data

不过,我不想每次都作出POST请求,但我宁愿要一次对网站进行身份验证并保持连接。

我在寻找的是一个干净而稳定的解决方案,它可以让我能够控制边缘情况,如提供的错误凭据。

我不习惯使用NSURLConnection,因为该解决方案在iOS9中已弃用。我需要一个NSURLSession的解决方案。

如果我在上述链接解决方案中遗漏了某些内容,请告知我们。我相信有人也有这个问题。此外,该网站具有SSL保护。

亲切的问候

+0

如何验证您的验证码是否可以在请求中提供标题?它是一个UI或WK网络视图? – Wain

+0

我正在使用UIWebView。从Web上查看时,身份验证是基本的HTTP身份验证弹出窗口。如果您尝试访问没有适当的凭据,您将获得401授权响应代码/状态。 – Armin

回答

5

我不能完全肯定此人符合你的要求最好的方法,但如果你可以使用WKWebView,也许你可以简单地依靠身份验证挑战委托方法?见我的回答here为好,相关的代码片段是:

func webView(webView: WKWebView, didReceiveAuthenticationChallenge 
      challenge: NSURLAuthenticationChallenge, 
    completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) { 

    let creds = NSURLCredential(user:"username", password:"password", persistence: NSURLCredentialPersistence.ForSession) 
    completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, creds) 
} 

我还没有尝试过自己,但文件说,该证书应用于会话,从链接产生的额外所以应该请求工作。即使不是这样,只会导致再次调用该方法,您可以再次提供证书。

这只是一个问题,你必须从alert或类似的地方获取名字和密码(也可以更优雅地存储凭据,以便随后调用委托方法更优雅)。

您也写过您使用SSL,所以我认为您熟悉App Transport安全标志(因为问题标题只包含“HTTP”,而不是“HTTPS”,您可能需要它工作顺利,否则看到我链接的问题)。

+0

是的,使用WKWebView简化它。在提出这个问题的时候,我不确定WKWebView是否适合我,但它确实解决了这个问题。这可能是目前最干净的解决方案。 – Armin

+0

很高兴我能帮到你。还要注意我的“优雅”的写作风格:“更多*优雅地存储* ......更优雅*”......你没有以英语征求意见的好事,我显然是个蠢人...... :) – Gero

+0

不用担心,对我来说也是优雅的作品。 :) – Armin

0

您不应该需要使用POST或连接或会话。您应该创建一个可变的URL请求并设置一个auth头。然后询问Web视图以加载请求。维基百科

验证报头信息:

  1. 用户名和密码相结合,与一个单一的结肠。
  2. 生成的字符串使用Base64的RFC2045-MIME变体进行编码,但不限于76字符/行。
  3. 然后将授权方法和空间即“基本”放在编码的字符串之前。

例如,如果用户端使用阿拉丁作为用户名和OPENSESAME作为密码,然后领域形成如下:

Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l 
+0

不幸的是,这似乎只适用于第一次请求。由于缺少授权,网络视图(菜单链接等)中的每个新请求都将失败。你确定会议不是必需的吗? – Armin

+0

会话不等同于网络会话。服务器应该返回一个带有一些认证令牌的cookie并使用它。这将是一个网络会话(不是一个URL会话,这是非常不同的) – Wain

0

好的,这里是Swift 3代码。

extension MyController: WKNavigationDelegate { 
    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { 
     guard let u = self.webuser, let p = self.webp else { 
      completionHandler(.cancelAuthenticationChallenge, nil) 
      return 
     } 

     let creds = URLCredential.init(user: u, password: p, persistence: .forSession) 
     completionHandler(.useCredential, creds) 
    } 
}