Swift 2 - Xcode 7.0 Cannot Access HTTPS site with

2019-03-15 14:11发布

Experts, I'm a Beginner in IOS 9 / XCODE 7 / Swift 2 Development Kit

I'm trying to create an ios app that simply route to Web Application in HTTPS protocol. Below is my code so far in ViewController.swift

import UIKit

class ViewController: UIViewController {

    @IBOutlet var myWebView: UIWebView!

    /**
     * Function to Display the Web Application initial URL
     */
    func loadAppURL(){
        let siteAddress = "https://domain:8443/path/to/page"
        let url = NSURL (string: siteAddress)
        let urlRequest = NSURLRequest(URL: url!)
        myWebView.loadRequest(urlRequest)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        loadAppURL()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

While Building my App it shows the below Error Message

2015-10-01 01:05:13.879 Web Page Tester[2947:31838] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9807)

and if i try building my app instead of "https://domain:8443/path/to/page" with "http://www.apple.com" its works fine.

I can access my web application in Safari and it asks for accepting the security risks. and i accept it and i can access my Application.

Guide me to fix my issues, Thanks in advance.

5条回答
放荡不羁爱自由
2楼-- · 2019-03-15 14:28

In Swift 3.

Step 1. Add NSURLConnectionDelegate to your viewcontroller, to overwrite methods.

class ViewController: UIViewController, NSURLConnectionDelegate {

Step 2. Override viewDidLoad

override func viewDidLoad() {
        super.viewDidLoad()

        let siteAddress = "https://mysiteaddress"
        let url = URL(string: siteAddress)
        let urlRequest = URLRequest(url: url!)
        let urlConnection:NSURLConnection = NSURLConnection(request: urlRequest, delegate: self)!
        webView.loadRequest(urlRequest)
    }

Step 3 Overwrite canAuthenticateAgainstProtectionSpace and didReceive challenge

func connection(_ connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: URLProtectionSpace) -> Bool {
    print("\ncanAuthenticateAgainstProtectionSpace method Returning True\n")
    return true
}

func connection(_ connection: NSURLConnection, didReceive challenge: URLAuthenticationChallenge) {
    print("did autherntcationchallenge = \(challenge.protectionSpace.authenticationMethod)")

    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust  {
        print("\nsend credential Server Trust\n")
        let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
        challenge.sender!.use(credential, for: challenge)

    }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic{
        print("send credential HTTP Basic")
        let defaultCredentials: URLCredential = URLCredential(user: "user", password: "password", persistence:URLCredential.Persistence.forSession)
        challenge.sender!.use(defaultCredentials, for: challenge)

    }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM{
        print("\nsend credential NTLM\n")

    } else{
        challenge.sender!.performDefaultHandling!(for: challenge)
    }

}

Thanks Navas Basheer for the original solution! Saved me a ton of time

查看更多
狗以群分
3楼-- · 2019-03-15 14:28

edit Info.plist, Add:

  1. App Transport Security Settings
  2. Allow Arbitrary Loads , value is YES

it's work for me, XCode 7.3

查看更多
forever°为你锁心
4楼-- · 2019-03-15 14:35

1- Create category "NSURLRequestCategory" -> after import this category to your bridge file created by xcode (don't forget to let xCode create one if you dont haven't) and put this code :

    @implementation NSURLRequest (NSURLRequestCategory)

+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host
{
    return YES;
}
@end

Create your load request UIWebView normally :

webView.delegate = self
let myURL = URL(string: Constants.URL_DOMAINE)
let request = URLRequest(url: myURL!)
webView.loadRequest(request)

Enjoyyy :D

查看更多
我欲成王,谁敢阻挡
5楼-- · 2019-03-15 14:44

Finally I fixed it

Xcode will reject un-trusted self signed certificates from servers by default.

we can override this Using NSURLConnection and can communicate with a self-signed server, since we have the ability to control the authentication through the additional delegate methods which are not available to a UIWebView. So using connection:didReceiveAuthenticationChallenge we can authenticate against the self signed server.

References NSURLAuthenticationChallenge Docs , @Lilo Lu's Question

I Resolved My Issue in below steps
Step 1 : Defined a NSURLConnection in viewDidLoad() method of my viewController.swift as follows

 override func viewDidLoad() {
    super.viewDidLoad()

    let siteAddress = "https://domain:8443/path/to/page"
    let url = NSURL (string: siteAddress)
    let urlRequest = NSURLRequest(URL: url!)
    let urlConnection:NSURLConnection = NSURLConnection(request: request, delegate: self)!
    myWebView.loadRequest(urlRequest)
 }

Step 2 : used NSURLConnection delegate methods

    func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool{
        print("canAuthenticateAgainstProtectionSpace method Returning True")
        return true
    }


    func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge){

        print("did autherntcationchallenge = \(challenge.protectionSpace.authenticationMethod)")

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

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

        }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM{
            print("send credential NTLM")

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

and that worked !!

查看更多
我命由我不由天
6楼-- · 2019-03-15 14:47

You can add the following to your plist

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

enter image description here

查看更多
登录 后发表回答