web-dev-qa-db-fra.com

WKWebView ne charge pas l'URL https?

J'ai un WKWebView qui devrait charger l'URL suivante: 

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

Elle est le code que j'utilise: 

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


}

Remarque: j'utilise le SDK iOS 8.4.

Pourquoi Safari mobile charge-t-il cette URL mais pas WKWebView?

21
confile

Ajoutez ceci à votre plist

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

Voici l'explication de ce changement dans la version 9.0 http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/

En outre, si vous souhaitez le rendre plus sécurisé, vous disposez d'un moyen plus complexe de le faire.

23
Randall Meyer

Pour moi, le problème était dû à la vérification de la confiance du serveur de WKWebView.

Pour résoudre ce problème, je devais gérer le rappel d'authentification par défi et renvoyer des informations d'identification de confiance du serveur.

Swift 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)
    }
}
7
Matthew Cawley

J'ai eu un problème similaire avec un site également protégé par un certificat TLS 1.2 de haute sécurité. Pour que WKWebView accepte le certificat du serveur, j'ai ajouté ce code à mon délégué du contrôleur d'affichage 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);
    }
}
2
saswanb

pas sûr si la même raison d'erreur, mais le problème était le même pour moi sous iOS9

certains domaines ne peuvent pas être chargés 

s'est avéré que le problème était en 

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

et fournir en retour

completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);

où j'aurais dû revenir 

completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);

J'utilisais du code incorrect de https://github.com/ShingoFukuyama/WKWebViewTips

1
Peter Lapisu
// 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>

si WKWebView ne supporte pas, déclarez le fichier .m en dessous du code:

entrez le code ici

@interface WebScannerViewController()
{

 WKWebView *webView;

}

@fin

@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);

}

0
Ramani Hitesh

Si vous êtes dans une application MacOS en mode bac à sable, vous devez définir la fonctionnalité Connexions sortantes (client). Vous n'avez pas besoin de jouer avec Allow Abitrary Loads qui ne devrait pas entrer en jeu pour les fichiers de confiance https. demandes.  Xcode Capabilities Screenshot showing the Outgoing Connections (Client) checkbox checked

Toutefois, pour iOS, autoriser les connexions client est la valeur par défaut. Vous devrez peut-être donc implémenter des méthodes WKNavigationDelegate pour gérer la sécurité. Assurez-vous de ne pas simplement faire confiance à des certificats non fiables. Cette vidéo Swift Talk d’objc.io est la meilleure ressource que je connaisse, elle vaut certainement 20 minutes si vous travaillez dans ce domaine: https://talk.objc.io/episodes/S01E57-certificate-pinning

0
nteiss