【问题标题】:WKWebView does not load https URL?WKWebView 不加载 https URL?
【发布时间】:2015-09-07 11:27:37
【问题描述】:

我有一个 WKWebView,它应该加载以下网址:

https://buchung.salonmeister.de/place/#offer-details-page?id=907599&venueId=301655

她是我使用的代码:

import UIKit
import WebKit


class MMWKBrowserController: UIViewController {

  private let closeButtonSelector: Selector = "closeButtonTapped:"

  private var urlString: String
  private let request: NSMutableURLRequest

  private var webView: WKWebView!
  private var twoLineTitleView: UIView!
  private var titleLabel: UILabel?
  private var subTitleLabel: UILabel?
  private var indicator: UIActivityIndicatorView!


  init(urlString: String) {
    self.urlString = urlString

    println("*** Using MMWKBrowserController ***")

    var url: NSURL? = NSURL(string: urlString)
    if url == nil {
      var escapedString: String = urlString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
      self.urlString = escapedString
      url = NSURL(string: escapedString)
    }

    println("url: \(url)")
    request = NSMutableURLRequest(URL: url!)

    request.setValue("Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H141 Safari/600.1.4", forHTTPHeaderField: "UserAgent")

    super.init(nibName: nil, bundle: nil)
  }

  required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }


  deinit {
    self.webView.removeObserver(self, forKeyPath: "loading")
    self.webView.removeObserver(self, forKeyPath: "title")
    self.webView.removeObserver(self, forKeyPath: "URL")
    self.webView.removeObserver(self, forKeyPath: "estimatedProgress")
    self.webView.stopLoading()
  }


  override func viewDidLoad() {
    super.viewDidLoad()
    createNavigationView()


    self.navigationController?.navigationBar.tintColor = MGColor.actionColor

    let config = WKWebViewConfiguration()
    self.webView = WKWebView(frame: self.view.bounds, configuration: config)
    self.view.addSubview(self.webView)


    indicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
    //indicator.backgroundColor = UIColor(white: 0.1, alpha: 0.5)
    webView.addSubview(indicator)

    self.webView.snp_makeConstraints { (make) -> Void in
      make.edges.equalTo(self.view)
    }

    indicator.snp_makeConstraints { (make) -> Void in
      make.center.equalTo(self.webView)
    }

    webView.addObserver(self, forKeyPath: "loading", options: NSKeyValueObservingOptions.New, context: nil)
    webView.addObserver(self, forKeyPath: "title", options: NSKeyValueObservingOptions.New, context: nil)
    webView.addObserver(self, forKeyPath: "URL", options: NSKeyValueObservingOptions.New, context: nil)
    webView.addObserver(self, forKeyPath: "estimatedProgress", options: NSKeyValueObservingOptions.New, context: nil)
  }


  override func viewDidDisappear(animated: Bool) {
    super.viewDidDisappear(animated)
    self.webView.stopLoading()
  }


  private func createNavigationView() {
    let closeItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Stop, target: self, action: closeButtonSelector)
    self.navigationItem.leftBarButtonItem = closeItem

    // create center view
    let titleViewWidth = self.view.frame.size.width - 100

    twoLineTitleView = UIView(frame: CGRectMake(0, 0, titleViewWidth, 44))

    titleLabel = UILabel(frame: CGRectMake(0, 6, titleViewWidth, 16))
    titleLabel?.backgroundColor = UIColor.clearColor()
    titleLabel?.font = UIFont.boldSystemFontOfSize(16)
    titleLabel?.textAlignment = NSTextAlignment.Center

    subTitleLabel = UILabel(frame: CGRectMake(0, 21, titleViewWidth, 20))
    subTitleLabel?.backgroundColor = UIColor.clearColor()
    subTitleLabel?.font = UIFont.systemFontOfSize(10)
    subTitleLabel?.textAlignment = NSTextAlignment.Center

    twoLineTitleView.addSubview(titleLabel!)
    twoLineTitleView.addSubview(subTitleLabel!)
    self.navigationItem.titleView = twoLineTitleView
  }



  override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    self.webView.loadRequest(self.request)

  }


  func closeButtonTapped(sender: UIBarButtonItem) {
    self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
  }


  override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {

    if let wk = object as? WKWebView {
      switch keyPath {
      case "loading":
        if let val: AnyObject = change[NSKeyValueChangeNewKey] {
          if let val = val as? Bool {
            if val {
              self.indicator.startAnimating()
            }
            else {
              self.indicator.stopAnimating()
            }
          }
        }
      case "title":
        self.titleLabel?.text = self.webView.title
      case "URL":
        self.subTitleLabel?.text = self.webView.URL?.URLString
      case "estimatedProgress":
        println("progress: \(Int32(self.webView.estimatedProgress*100))")

      default: break
      }
    }
  }


}

注意:我使用 SDK iOS 8.4

为什么移动版 Safari 会加载此网址,而 WKWebView 却没有?

【问题讨论】:

  • 您使用的是哪个 SDK? iOS8 还是 iOS 9?
  • 这部分 url 加载正常:buchung.salonmeister.de,其余部分可能包含一些 webview 工具包无法识别的字符。尝试不同的选择。
  • 我添加了webView.loadRequest(request)(参见screenshot)后,您的 webView 对我有效,但请注意,您的 URL 似乎指向的页面不再存在。
  • 在移动 Safari 中加载 URL,您会看到页面加载。
  • 您可能需要将www 添加到您的字符串中,苹果似乎对其格式非常挑剔。

标签: ios objective-c iphone swift wkwebview


【解决方案1】:

将此添加到您的 plist 中

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

这是 9.0 中此更改的解释 http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/

此外,如果您想将其设置得更安全,它会为您提供更复杂的方法。

【讨论】:

  • Josh,你能解释一下为什么 AppStore 会因为 plist 中的这些行而拒绝你的应用程序吗?
  • 我发现了为什么它有时会被 Apple 拒绝。如果您转到作者发布的链接,有一种更好的方法可以做到这一点,您可以出于安全原因指定您正在访问的网站的实际域名。它还警告说不建议允许任意加载。
【解决方案2】:

对我来说,这个问题是由 WKWebView 的服务器信任检查引起的。

为了解决这个问题,我必须处理质询身份验证回调并返回服务器信任凭据。

斯威夫特 4

func webView(_ webView: WKWebView, 
    didReceive challenge: URLAuthenticationChallenge, 
    completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) 
{
    if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust)
    {
        let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
        completionHandler(.useCredential, cred)
    }
    else
    {
        completionHandler(.performDefaultHandling, nil)
    }
}

【讨论】:

    【解决方案3】:

    如果您在沙盒 macOS 应用程序中,则需要设置传出连接(客户端)功能,您不需要弄乱不应该进入的 Allow Abitrary Loads播放受信任的 https 请求。

    然而,对于 iOS,允许客户端连接是默认设置,因此您可能需要实现 WKNavigationDelegate 方法来处理安全性。确保您不只是信任不受信任的证书。这个来自 objc.io 的 Swift Talk 视频是我所知道的最好的资源,如果你在这个领域工作,绝对值得花 20 分钟:https://talk.objc.io/episodes/S01E57-certificate-pinning

    【讨论】:

      【解决方案4】:

      我的网站也受到了高安全性 TLS 1.2 证书的保护,也遇到了类似的问题。为了让 WKWebView 接受服务器的证书,我将此代码添加到我的 Web 视图控制器委托中:

      -(void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
      {
          if ([[[challenge protectionSpace]authenticationMethod] isEqualToString: @"NSURLAuthenticationMethodServerTrust"]) {
              SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
              CFDataRef exceptions = SecTrustCopyExceptions(serverTrust);
              SecTrustSetExceptions(serverTrust, exceptions);
              CFRelease(exceptions);
              newCredential = [NSURLCredential credentialForTrust:serverTrust];
              completionHandler(NSURLSessionAuthChallengeUseCredential, newCredential);
          } else {
              completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, newCredential);
          }
      }
      

      【讨论】:

        【解决方案5】:

        不知道是不是同样的错误原因,但我在iOS9下的问题是一样的

        部分域名无法加载

        原来问题出在

        - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
        

        并提供回馈

        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
        

        我应该返回的地方

        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
        

        我使用了来自https://github.com/ShingoFukuyama/WKWebViewTips的错误代码

        【讨论】:

        • 我没有明白你的意思。你能在你的描述中更详细吗?我不使用didReceiveAuthenticationChallenge的方法。
        • 我确实遇到了类似的错误行为,似乎 webview 没有加载 https,原来这是 didReceiveAuthenticationChallenge 中的问题
        • 能否请您发布更多代码。你的didReceiveAuthenticationChallenge 方法看起来如何?
        • 尝试返回 completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);是否解决了你的问题
        • 这条线是做什么用的?
        【解决方案6】:
        // Add plist file 
        <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
        <key>NSExceptionDomains</key>
        <dict>
            <key>google.com</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
        

        如果 WKWebView 不支持,则在代码下方声明 .m 文件:

        @interface WebScannerViewController()
        {
        
         WKWebView *webView;
        
        }
        
        
        @end
        
        
        
        @implementation WebScannerViewController
        
         - (void)viewDidLoad   {
        
            [super viewDidLoad];
            webView.hidden=YES;
        
            webView.UIDelegate = self;
            webView.navigationDelegate = self;
            self.loadingSign.hidden = NO;
        
        
                webView.frame=CGRectMake(0, 94, Width, Height-128);
            }
        

        【讨论】:

        • 感谢您显示上面的 plist 更新,这是正确的做法,因此苹果不会出于安全原因拒绝该应用程序。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-09-25
        • 2020-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-29
        • 2021-06-26
        相关资源
        最近更新 更多