How to call https url in uiwebview (swift)?

2019-07-21 19:20发布

I have https url with self-sign certication in UIWEBView ,but it does not work.

Error is NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)...

how can I to allow any certication in uiwebview by swift

Do you have any idea that fix this problem?

3条回答
放荡不羁爱自由
2楼-- · 2019-07-21 19:33

i find a way to do this,but i think this is not a good way.

step 1------use NSURLConnection in override func viewDidLoad(){} section request = NSURLRequest(URL:url)

    let urlConnection:NSURLConnection = NSURLConnection(request: request, delegate: self)!

step 2------ use the NSURLConnection delegate to

func connection(connection: NSURLConnection, didFailWithError error: NSError){
    println("didFailWithError")
}

func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool{
    println("canAuthenticateAgainstProtectionSpace")
    //return [protectionSpace.authenticationMethodisEqualToString:NSURLAuthenticationMethodServerTrust];
    return true
}

func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge){
    println("did autherntcationchallenge = \(challenge.protectionSpace.authenticationMethod)")

    //if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust && challenge.protectionSpace.host == "myDomain.com" {

    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust  {
        println("send credential Server Trust")
        let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
        challenge.sender.useCredential(credential, forAuthenticationChallenge: challenge)

    }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic{
        println("send credential HTTP Basic")
        var defaultCredentials: NSURLCredential = NSURLCredential(user: "username", password: "password", persistence:NSURLCredentialPersistence.ForSession)
        challenge.sender.useCredential(defaultCredentials, forAuthenticationChallenge: challenge)

    }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM{
        println("send credential NTLM")
        if challenge.previousFailureCount > 0 {
            //如果连续两次验证未通过,则终止, 还需要返回自定义出错界面
            //handle bad credentials scenario
        }

        var defaultCredentials: NSURLCredential = NSURLCredential(user: "username", password: "password", persistence:NSURLCredentialPersistence.ForSession)
        challenge.sender.useCredential(defaultCredentials, forAuthenticationChallenge: challenge)
        }

    } else{
        challenge.sender.performDefaultHandlingForAuthenticationChallenge!(challenge)
    }
    //challenge.sender.performDefaultHandlingForAuthenticationChallenge!(challenge)
    //challenge.sender.continueWithoutCredentialForAuthenticationChallenge(challenge)
}

/*
func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge) {


}*/
func connection(connection: NSURLConnection, didCancelAuthenticationChallenge challenge: NSURLAuthenticationChallenge){
    println("didCancelAuthenticationChallenge")
}
/*
- (void)connection: (NSURLConnection *)connection willSendRequestForAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge
{
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}*/

func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse){
    println("-----received response");



    // remake a webview call now that authentication has passed ok.

    //_authenticated =YES;

    //[_webloadRequest:_request];
   webView.loadRequest(request)


    // Cancel the URL connection otherwise we double up (webview + url connection, same url = no good!)

    //[_urlConnectioncancel];
}

it can work

sorry for my poor english skill

查看更多
Viruses.
3楼-- · 2019-07-21 19:40

This is the Swift 3 approach...

import UIKit
import Security

class ViewController: UIViewController, UIWebViewDelegate, NSURLConnectionDelegate {

    @IBOutlet weak var webView: UIWebView!
    var loadingUnvalidatedHTTPSPage:Bool!
    var connection:NSURLConnection!
    let path = "https://my.url.com.mx"

    override func viewDidLoad() {
        super.viewDidLoad()

        webView.delegate = self
        webView.scalesPageToFit = true
        webView.contentMode = .scaleAspectFit

        let requestObj = NSURLRequest.init(url: URL(string: path)!, cachePolicy: NSURLRequest.CachePolicy.useProtocolCachePolicy, timeoutInterval: 10.0)
        let conn:NSURLConnection = NSURLConnection(request: requestObj as URLRequest, delegate: self)!
        conn.start()

        self.loadingUnvalidatedHTTPSPage = true
        webView.loadRequest(requestObj as URLRequest)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    // MARK - DELEGATE METHODS WEBVIEW
    private func webView(webView: UIWebView!, didFailLoadWithError error: NSError!) {
        print("Webview fail with error \(error)");

        if(error.domain == NSURLErrorDomain){
            if (error.code == NSURLErrorServerCertificateHasBadDate || error.code == NSURLErrorServerCertificateUntrusted   ||
                error.code == NSURLErrorServerCertificateHasUnknownRoot || error.code == NSURLErrorServerCertificateNotYetValid) {
                print("\n ---- :C ....")
            }
        }
    }

    private func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) ->Bool{
        print("Webview iniciando");
        if (self.loadingUnvalidatedHTTPSPage!) {
            self.connection = NSURLConnection(request: request as URLRequest, delegate: self)
            self.connection.start();
            return false;
        }
        return true;
    }

    private func webViewDidStartLoad(webView: UIWebView!) {
        print("Webview started Loading")
    }

    private func webViewDidFinishLoad(webView: UIWebView!) {
        print("Webview did finish load")
    }


    // MARK - NSURLConnectionDelegate methods
    func connection(_ connection: NSURLConnection, willSendRequestFor challenge: URLAuthenticationChallenge) {
        let trust:SecTrust = challenge.protectionSpace.serverTrust!;
        let cred:URLCredential = URLCredential(trust: trust)
        challenge.sender?.use(cred, for: challenge)
    }

    func connection(_ connection: NSURLConnection, NSURLConnection response:URLResponse){
        let requestObj:NSURLRequest = NSURLRequest(url: URL(string: path)!, cachePolicy: NSURLRequest.CachePolicy.returnCacheDataElseLoad, timeoutInterval: 20.0)
        self.loadingUnvalidatedHTTPSPage = false
        self.webView.loadRequest(requestObj as URLRequest)
        self.connection.cancel()
    }

}

Don't forget to set "Allow Arbitrary Loads" = YES in your .plist file.

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
查看更多
再贱就再见
4楼-- · 2019-07-21 19:40

You need to bundle your cert with your app. Then, the cert will end up being trusted by app networking components, including your web view.

查看更多
登录 后发表回答