web-dev-qa-db-fra.com

Autoriser les certificats SSL non vérifiés dans WKWebView

J'essaie de charger une URL HTTPS avec un certificat auto-signé dans un WKWebView pour iOS 8 et cela continue à échouer. La solution de contournement utilisée avec UIWebView (à l'aide de setAllowsAnyHTTPSCertificate de NSUrlRequest) ne semble pas fonctionner. Est-ce que quelqu'un connaît une solution de contournement? 

Je n'ai pas besoin d'une solution valable pour AppStore, car je n'ai besoin d'accéder qu'aux sites de certificats auto-signés lors des phases de développement, pas de production, mais c'est vraiment un problème pour le développement et le test des instances de serveur.

Merci d'avance.

17
Roi

Ceci est corrigé dans iOS 9! WKWebView appelle finalement webView(_:didReceiveAuthenticationChallenge:completionHandler:) sur WKNavigationDelegate. Malheureusement, cela ne fonctionne pas si vous exécutez du code intégré à Xcode 7 sur des appareils iOS 8 (du moins pas lors de mes tests initiaux).

Dans mon exemple ci-dessous, je ne fais en réalité rien avec le certificat et le laisse passer sans faire aucune validation supplémentaire (évidemment un mauvais plan pour le code de production). Voir Documents d'Apple (Listing 3) pour plus de détails sur ce qu'ils veulent que vous fassiez ici.

Rapide:

func webView(webView: WKWebView, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge,
    completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
        let cred = NSURLCredential.init(forTrust: challenge.protectionSpace.serverTrust!)
        completionHandler(.UseCredential, cred)
}

Swift 3:

let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)

Swift 4:

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

Objectif c

NSURLCredential * credential = [[NSURLCredential alloc] initWithTrust:[challenge protectionSpace].serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
28
jvoll

On dirait qu'il n'y a peut-être pas de solution à ce stade (iOS 8.1.1). On aurait pu s’attendre à ce que la méthode WKNavigationDelegate webView:didReceiveAuthenticationChallenge:completionHandler: gère ce problème, mais en se basant sur ceci discussion sur le forum pour les développeurs Apple un employé d’Apple confirme que cette méthode de délégation n’a pas été appelée lorsque des certificats auto-signés sont rencontrés.

4
user2067021

J'ai la même erreur et j'essaie de la résoudre en utilisant la réponse la plus votée ci-dessus. J'ai utilisé le code suivant pour créer un objet NSURLCredential, mais cela a échoué.

NSURLCredential * credential = [[NSURLCredential alloc] initWithTrust:[challenge protectionSpace].serverTrust];

Ensuite, j'ai trouvé une solution dans Forums des développeurs Apple . Cela m'a aidé: 

- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
  NSLog(@"Allow all");
  SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
  CFDataRef exceptions = SecTrustCopyExceptions (serverTrust);
  SecTrustSetExceptions (serverTrust, exceptions);
  CFRelease (exceptions);
  completionHandler (NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:serverTrust]);
  }
3
guozqzzu

Ouvrez l’URL dans Safari sur le périphérique une fois. Vous serez invité à accepter le certificat. Une fois accepté, il devrait également fonctionner dans votre application, car le certificat est maintenant connu du périphérique . Il s’agit d’une solution de contournement par périphérique qui n’affectera en aucun cas votre application au moment de la publication.

1
dogsgod

Essaye ça: 

 func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

    if let serverTrust = challenge.protectionSpace.serverTrust {
        let credential = URLCredential(trust: serverTrust)
        completionHandler(.useCredential, credential)
    }else{
         completionHandler(.useCredential, nil)
    }

}
0
Faipdeoiad

La suite fonctionne dans mon cas pour charger l'URL HTTP ou HTTPS

func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    return completionHandler(.useCredential, nil)
}

Si vous chargez une URL HTTP non sécurisée, telle que http://www.example.com, vous devez ouvrir Info.plist et activer NSExceptionAllowsInsecureHTTPLoads, comme suit:

 enter image description here

0
AamirR

J'ai passé beaucoup de temps à regarder cela, en tant que novice iOS, aucune des solutions proposées n'était complète à mon avis. Voici donc ce que j’ai fait pour que WKWebView fonctionne dans mon cas (vue Web très simple nécessitant l’accès à un certificat auto-signé pour dev only):

Première chose: dans mon fichier racine Info.plist, j'ai ajouté les "Paramètres de sécurité du transport d'application" en tant que dictionnaire et ajouté l'élément "Autoriser les charges arbitraires" avec la valeur YES.

 App Transport Security Settings Allow Arbitrary Loads

Deuxièmement: j'ai ajouté ce code à mon ViewController (hérite de UIViewController et de WKNavigationDelegate) - il provient de plusieurs réponses ailleurs.

func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    guard let serverTrust = challenge.protectionSpace.serverTrust else { return completionHandler(.useCredential, nil) }
    let exceptions = SecTrustCopyExceptions(serverTrust)
    SecTrustSetExceptions(serverTrust, exceptions)
    completionHandler(.useCredential, URLCredential(trust: serverTrust))
}

NOTEZ QUE CETTE SOLUTION SERA PROBABLEMENT REJETÉE PAR L'APP STORE - JE SOUMETTRE À L'APP STORE AVEC "Autoriser les charges arbitraires" ARTICLE AVEC UNE VALEUR N °

0
simong5443