How do I accept a self-signed SSL certificate using iOS 7's NSURLSession

前端 未结 3 1561
星月不相逢
星月不相逢 2020-12-29 08:16

I have the following code (swift implementation):

func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLPr         


        
相关标签:
3条回答
  • 2020-12-29 08:52

    Swift 5 Solution

    Note These settings are for testing purpose only, don't push changes in production app

    Steps

    1. Add "Allow Arbitrary Loads" key to "YES" under "App Transport Security Settings" in info.plist

    2. Create new session object with delegate to self

      let config = URLSessionConfiguration.default
      let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)

    3. Implement URLSessionDelegate protocol to current class

      extension YouClass: URLSessionDelegate{ func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!)) } }

    Modified version of: https://stackoverflow.com/a/30820452/3754976

    0 讨论(0)
  • 2020-12-29 09:01

    inherit class with URLSessionDelegate

    create a session object

    let config = URLSessionConfiguration.default
    
    
    let session = Foundation.URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
    
    
     let task = session.dataTask(with: httpRequest as URLRequest, completionHandler: {requestData, response, errorData -> Void in
    
                if errorData == nil {
    
                    dataCallback(requestData! as NSData)
                }
                else {
    
                    let error = NSError(domain: "Err-1001", code: 11, userInfo:nil)
                    failureCallback(error)
                }
            });
    
            task.resume() 
    

    Add delegate methad

    func urlSession(_ session: URLSession, task: URLSessionTask, didReceive     challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
         completionHandler(
            .useCredential,
            URLCredential(trust: challenge.protectionSpace.serverTrust!))
     }
    

    add this in your info.plist file

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>xyc.com</key>
            <dict>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <true/>
                <key>NSExceptionMinimumTLSVersion</key>
                <string>TLSv1.2</string>
                <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
                <false/>
                <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
                <true/>
                <key>NSThirdPartyExceptionMinimumTLSVersion</key>
                <string>TLSv1.2</string>
                <key>NSRequiresCertificateTransparency</key>
                <false/>
            </dict>
        </dict>
    </dict>
    
    0 讨论(0)
  • 2020-12-29 09:17

    Both connection:canAuthenticateAgainstProtectionSpace: and connection:didReceiveAuthenticationChallenge: are deprecated in iOS 8 anyway so you should use other methods.

    What I am using in my projects is a delegate method of NSURLSessionDelegate. Adhere to that protocol then add this method:

    func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential!) -> Void) {
        completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust))
    }
    

    Then, when you use initialize NSURLSession with delegate set to self. For example:

    var session = NSURLSession(configuration: configuration, delegate: self, delegateQueue:NSOperationQueue.mainQueue())
    

    Then use that session instance to call dataTaskWithRequest method on:

    var task = session.dataTaskWithRequest(request){
        (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
        if error != nil {
            callback("", error.localizedDescription)
        } else {
            var result = NSString(data: data, encoding:
                NSASCIIStringEncoding)!
        }
    }
    task.resume()
    

    Complete working example can be found here.

    For security reasons, if you use a self-signed certificate I recommend also implementing public key pinning (https://gist.github.com/edwardmp/df8517aa9f1752e73353)

    0 讨论(0)
提交回复
热议问题