Xcode 7 / iOS 9: how to enable a self-signed certificate for NSURLSession

To test my application, I configured Apache 2.4.12 server with TLS 1.2 and a self-signed certificate. The problem is that when I run my application and I try to contact my local server, I get this error:

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
nil
Optional(Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred  and a secure connection to the server cannot be made." UserInfo= {NSLocalizedDescription=An SSL error has occurred and a secure connection to the  server cannot be made., NSLocalizedRecoverySuggestion=Would you like to connect  to the server anyway?...

and this is because a self-signed certificate is not reliable. I read somewhere in stackoverflow that in the class where I use NSURLSession (), I had to add the following delegate:

func URLSession(session: NSURLSession,
    task: NSURLSessionTask,
    didReceiveChallenge challenge: NSURLAuthenticationChallenge,
    completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?)
    -> Void) {

    completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!))
}

and then do:

func requestLoginWithURL (requestURL: NSURL, completionHandler: (success: Bool?) -> Void) {
    let configuration =
    NSURLSessionConfiguration.defaultSessionConfiguration()

    let urlRequest: NSURLRequest = NSURLRequest(URL: requestURL)

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

    /*
    dataTaskWithRequest: creates an HTTP request for the specified URL request object, and calls a handler upon completion.
    */
    let task = session.dataTaskWithRequest( ...)
}

but it looks like it still doesn't work. So I was wondering if there is a way to force a self-signed certificate to be accepted without adding this xml code to info.plist to disable secure communication of any form. Here is httpd-ssl.conf on my server:

<VirtualHost *:443>
      DocumentRoot "/Applications/AMPPS/www"
      ServerName localhost
      SSLEngine on
      SSLProtocol all -SSLv2 -SSLv3
      SSLHonorCipherOrder on
      SSLCertificateFile "/Applications/AMPPS/apache/conf/server.crt"
      SSLCertificateKeyFile "/Applications/AMPPS/apache/conf/server.key"
</VirtualHost>

? , , ITS 9 ATS. .

info.plist, ATS :

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost</key>
        <dict>
            <!--Include to allow subdomains-->
            <key>NSIncludesSubdomains</key>
            <true/>
            <!--Include to allow HTTP requests-->
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <!--
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.1</string>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/> -->
        </dict>
    </dict>
</dict>

, , . , NSURLSession, :

class LoginService: NSObject, NSURLSessionDelegate {

func URLSession(session: NSURLSession,
    task: NSURLSessionTask,
    didReceiveChallenge challenge: NSURLAuthenticationChallenge,
    completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?)
    -> Void) {

    completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!))
}

...

}

- :

let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()

    let urlRequest: NSURLRequest = NSURLRequest(URL: requestURL)

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

    /*
    dataTaskWithRequest: creates an HTTP request for the specified URL request object, and calls a handler upon completion.
    */
    let task = session.dataTaskWithRequest(urlRequest...)

. , Apache 2.4.x, , TLS 1.2. , .

+4

Source: https://habr.com/ru/post/1608892/


All Articles