XCode 7 / iOS 9:如何为NSURLSession启用自签名证书

时间:2015-09-24 20:52:44

标签: ios ios9 xcode7 nsurlsession tls1.2

为了测试我的应用程序,我设置了一个带有TLS 1.2的服务器Apache 2.4.12和一个自签名证书。问题是,当我运行我的应用程序并尝试与本地服务器通信时,我收到此错误:

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?...

这是因为自签名证书不可靠的corse。我在stackoverflow中读到了某处,在我使用NSURLSession()的类中,我不得不添加以下委托:

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

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

然后执行:

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( ...)
}

但似乎无论如何这都行不通。所以我想知道是否有办法强制接受自我分配的证书,而不将该xml代码添加到info.plist以禁用任何形式的安全通信。 这是我服务器中的httpd-ssl.conf:

<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>

有没有办法让这项工作?只是为了向我的老师证明我正在构建符合iOS 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>

然而,正如解释here这还不够。在您将使用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的版本。 希望这会有所帮助。

0 个答案:

没有答案