如何使用WKWebView进行用户身份验证?

时间:2017-03-13 20:06:17

标签: javascript ios iphone swift

目标:检索accessToken和用户详细信息,而无需使用任何本机控件来输入用户凭据。使用SSO登录。

步骤:iOS应用和用户执行

1.User选择SSO登录选项

2.User重定向到SSO登录URL

3.SSO登录URL显示用于输入用户名和的JavaScript警报     密码。(在桌面和移动浏览器上,它没有显示任何内容     在webview中)

4.一旦用户输入凭证,他就会被重定向到我们的服务器,该服务器返回带有用户数据的html页面。

我尝试了什么: 尝试使用以下

func viewDidLoad(){
        let pref = WKPreferences()
        pref.javaScriptEnabled = true
        pref.javaScriptCanOpenWindowsAutomatically = true

        /* Create a config using pref*/
        let configuration = WKWebViewConfiguration()
        configuration.preferences = pref

        /* Instantiate the web view */

        let webviewFrame = CGRect(x:0,y: txtSSOLoginUrl.bounds.maxY, width: self.view.bounds.width, height: self.view.bounds.height - 40)
        webView = WKWebView(frame:webviewFrame,configuration: configuration)
        view.addSubview(webView)
        webView.navigationDelegate = self
        webView.uiDelegate  = self
        webView.load(request as URLRequest)
}

extension SSOLoginViewController:WKUIDelegate,WKNavigationDelegate{
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        UIApplication.shared.isNetworkActivityIndicatorVisible = true
        print("DID START NAV didStartProvisionalNavigation")

    }
    func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        print("RECEIVERD SERVER REDIRECT")

    }

    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        print("EERRORRR : \(error)")
    }


    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print ("ERRRRRR : \(error)")
    }

    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        print("runJavaScriptAlertPanelWithMessage")
        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)

        alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action) in
            completionHandler()
        }))

        self.present(alertController, animated: true, completion: nil)
        alertController.popoverPresentationController?.sourceView = self.view
    }

    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
        print("runJavaScriptConfirmPanelWithMessages")
        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)

        alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action) in
            completionHandler(true)
        }))

        alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
            completionHandler(false)
        }))

        self.present(alertController, animated: true, completion: nil)

        alertController.popoverPresentationController?.sourceView = self.view
    }

    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
        print("runJavaScriptTextInputPanelWithPrompt")
        let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .actionSheet)

        alertController.addTextField { (textField) in
            textField.text = defaultText
        }
        alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action) in
            if let text = alertController.textFields?.first?.text {
                completionHandler(text)
            } else {
                completionHandler(defaultText)
            }

        }))
        alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in

            completionHandler(nil)

        }))

        self.present(alertController, animated: true, completion: nil)
        alertController.popoverPresentationController?.sourceView = self.view
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        UIApplication.shared.isNetworkActivityIndicatorVisible = false
        print("DID FINISH NAV didFinish navigation")

    }

    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        print("DECIDE POLICY WKNavigationResponse \(navigationResponse)")
        decisionHandler(.allow)

    }

    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        print("DID RECEIVE URLAuthenticationChallenge")
         //var cred = URLCredential(user: "username", password: "Password123!", persistence: URLCredential.Persistence.none)
         //challenge.sender?.use(password, for: challenge)
        completionHandler(URLSession.AuthChallengeDisposition.useCredential, nil)

    }
 }

输出 没有看到警告询问用户凭据。

预期输出 使用用户名和密码文本字段获取警报以输入凭据。

1 个答案:

答案 0 :(得分:0)

为了解决这个问题,我们要做的是,使用服务器提供的HTML页面,后端在隐藏字段中使用所需的详细信息进行实际的重定向。该重定向URL被提供给了使用他们自己的SSO登录名的另一方,但是通过我们的应用程序在网络视图中提供了该URL。这不是解决问题的方法,而是一种解决方法。从来没有真正解决过这个问题。