Authentication with WKWebView in Swift

旧街凉风 提交于 2019-12-17 20:05:29

问题


In my iOS app, I would like to use a WKWebView to wrap an external URL in the application. This URL requires basic authentication (it needs user and password credential, like in the following screenshot).

After some investigation, I'm trying to use didReceiveAuthenticationChallenge method, in order to enable an automatic login, so I'm not understanding how it works.

This is my code.

import UIKit
import WebKit

class WebViewController: UIViewController, WKNavigationDelegate {

    var webView: WKWebView?

    private var request : NSURLRequest {
        let baseUrl = "https://unimol.esse3.cineca.it/auth/Logon.do"
        let URL = NSURL(string: baseUrl)!
        return NSURLRequest(URL: URL)
    }

    /* Start the network activity indicator when the web view is loading */
    func webView(webView: WKWebView,
                 didStartProvisionalNavigation navigation: WKNavigation){
        UIApplication.sharedApplication().networkActivityIndicatorVisible = true
    }

    /* Stop the network activity indicator when the loading finishes */
    func webView(webView: WKWebView,
                 didFinishNavigation navigation: WKNavigation){
        UIApplication.sharedApplication().networkActivityIndicatorVisible = false
    }

    func webView(webView: WKWebView,
                 decidePolicyForNavigationResponse navigationResponse: WKNavigationResponse,
                                                   decisionHandler: ((WKNavigationResponsePolicy) -> Void)){
        decisionHandler(.Allow)
    }

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

        if challenge.protectionSpace.host == "https://unimol.esse3.cineca.it/auth/Logon.do" {
            let user = "*******"
            let password = "******"
            let credential = NSURLCredential(user: user, password: password, persistence: NSURLCredentialPersistence.ForSession)
            challenge.sender?.useCredential(credential, forAuthenticationChallenge: challenge)
        }
    }

    override func viewDidLoad() {
        /* Create our preferences on how the web page should be loaded */
        let preferences = WKPreferences()
        preferences.javaScriptEnabled = false

        /* Create a configuration for our preferences */
        let configuration = WKWebViewConfiguration()
        configuration.preferences = preferences

        /* Now instantiate the web view */
        webView = WKWebView(frame: view.bounds, configuration: configuration)

        if let theWebView = webView {
            /* Load a web page into our web view */
            let urlRequest = self.request
            theWebView.loadRequest(urlRequest)
            theWebView.navigationDelegate = self
            view.addSubview(theWebView)
        }
    }
}

I'm facing with this exception:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Completion handler passed to -[MyUnimol.WebViewController webView:didReceiveAuthenticationChallenge:completionHandler:] was not called'

If I delete the didReceiveAuthenticationChallenge method, I'm able to reach the URL but is gives me, obliviously, wrong credentials.

Anyone could explain me what I'm doing wrong please?


回答1:


Add the following line:

completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, credential)

at the end of didReceiveAuthenticationChallenge solved the problem.




回答2:


i am late to party but still this can be useful for someone.

To support auth challenge in WKWebview Swift 4, complete code as below

func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        guard let hostname = webView.url?.host else {
            return
        }

        let authenticationMethod = challenge.protectionSpace.authenticationMethod
        if authenticationMethod == NSURLAuthenticationMethodDefault || authenticationMethod == NSURLAuthenticationMethodHTTPBasic || authenticationMethod == NSURLAuthenticationMethodHTTPDigest {
            let av = UIAlertController(title: webView.title, message: String(format: "AUTH_CHALLENGE_REQUIRE_PASSWORD".localized, hostname), preferredStyle: .alert)
            av.addTextField(configurationHandler: { (textField) in
                textField.placeholder = "USER_ID".localized
            })
            av.addTextField(configurationHandler: { (textField) in
                textField.placeholder = "PASSWORD".localized
                textField.isSecureTextEntry = true
            })

            av.addAction(UIAlertAction(title: "BUTTON_OK".localized, style: .default, handler: { (action) in
                guard let userId = av.textFields?.first?.text else{
                    return
                }
                guard let password = av.textFields?.last?.text else {
                    return
                }
                let credential = URLCredential(user: userId, password: password, persistence: .none)
                completionHandler(.useCredential,credential)
            }))
            av.addAction(UIAlertAction(title: "BUTTON_CANCEL".localized, style: .cancel, handler: { _ in
                completionHandler(.cancelAuthenticationChallenge, nil);
            }))
            self.parentViewController?.present(av, animated: true, completion: nil)
        }else if authenticationMethod == NSURLAuthenticationMethodServerTrust{
            // needs this handling on iOS 9
            completionHandler(.performDefaultHandling, nil);
        }else{
            completionHandler(.cancelAuthenticationChallenge, nil);
        }
    }


来源:https://stackoverflow.com/questions/37177751/authentication-with-wkwebview-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!