Alamofire con un certificate autofirmado / ServerTrustPolicy

Quiero usar Alamofire para comunicarse con mi server a través de una connection https con un certificate autofirmado. Mi entorno se ejecuta en localhost. Intenté conectarme, pero la respuesta siempre se ve así:

Success: false Response String: nil 

Lo he hecho con el siguiente código:

 import Foundation import UIKit import Alamofire class MessageView: UITableViewController { let defaultManager: Alamofire.Manager = { let serverTrustPolicies: [String: ServerTrustPolicy] = [ "localhost": .DisableEvaluation ] let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders return Alamofire.Manager( configuration: configuration, serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies) ) }() override func viewDidLoad() { super.viewDidLoad() defaultManager .request(.GET, "https://localhost:3443/message") .responseJSON { _, _, result in print("Success: \(result.isSuccess)") print("Response String: \(result.value)") } } } 

He creado los certificates del lado del server con esta línea de bash:

 openssl req -x509 -nodes -days 999 -newkey rsa:2048 -keyout server.key -out server.crt 

No sé qué estoy haciendo mal. La ayuda sería genial.

### Actualización ###

Aquí está la request de cURL. En mi opinión, no hay problema, ¿o estoy equivocado?

 curl -X GET https://localhost:3443/message -k -v * Trying ::1... * Connected to localhost (::1) port 3443 (#0) * TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 * Server certificate: teawithfruit > GET /message HTTP/1.1 > Host: localhost:3443 > User-Agent: curl/7.43.0 > Accept: */* > < HTTP/1.1 200 OK < Content-Type: application/json; charset=utf-8 < Content-Length: 1073 < Date: Tue, 15 Sep 2015 06:20:45 GMT < Connection: keep-alive < * Connection #0 to host localhost left intact [{"_id":"55f3ed2d81a334558241e2f4","email":"abc@def.com","password":"abc","name":"teawithfruit","language":"en","__v":0,"timestamp":1442049325159,"messages":[{"_id":"55f40553e568236589772c61","user":"55f3ed2d81a334558241e2f4","language":"en","message":"hello world","__v":0,"timestamp":1442055507301,"id":"55f40553e568236589772c61"},{"_id":"55f48b2b02e7b059b54e99f6","user":"55f3ed2d81a334558241e2f4","language":"en","message":"hello world","__v":0,"timestamp":1442089771312,"id":"55f48b2b02e7b059b54e99f6"}],"id":"55f3ed2d81a334558241e2f4"}] 

### Actualización 2 ###

Disculpa por la respuesta tardía. Estas son las dos debugPrints:

Solicitar debuggingImprimir:

 $ curl -i \ -H "Accept-Language: en-US;q=1.0" \ -H "Accept-Encoding: gzip;q=1.0,compress;q=0.5" \ -H "User-Agent: Message/com.teawithfruit.Message (1; OS Version 9.0 (Build 13A340))" \ "https://localhost:3443/message" 

Resultado debugImpresión:

 FAILURE: Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://localhost:3443/message, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://localhost:3443/message} 

### Actualización 3 ###

Aquí está el error completo con tal vez un problema ATS?

 nil $ curl -i \ -H "Accept-Language: en-US;q=1.0" \ -H "Accept-Encoding: gzip;q=1.0,compress;q=0.5" \ -H "User-Agent: Message/com.teawithfruit.Message (1; OS Version 9.0 (Build 13A340))" \ "https://localhost:3443/message" 2015-10-17 15:10:48.346 Message[25531:1001269] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802) FAILURE: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurnetworking and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x7fdc3044b740>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=<CFArray 0x7fdc2a7ca300 [0x10f7037b0]>{type = immutable, count = 1, values = ( 0 : <cert(0x7fdc31d31670) s: teawithfruit i: teawithfruit> )}, NSUnderlyingError=0x7fdc30064bd0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x7fdc3044b740>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=<CFArray 0x7fdc2a7ca300 [0x10f7037b0]>{type = immutable, count = 1, values = ( 0 : <cert(0x7fdc31d31670) s: teawithfruit i: teawithfruit> )}}}, NSLocalizedDescription=An SSL error has occurnetworking and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://localhost:3443/message, NSErrorFailingURLStringKey=https://localhost:3443/message, NSErrorClientCertificateStateKey=0} Success: false Response String: nil 

Debe agregar el dominio del port cuando cree su dictionary ServerTrustPolicy .

 let defaultManager: Alamofire.Manager = { let serverTrustPolicies: [String: ServerTrustPolicy] = [ "localhost:3443": .DisableEvaluation ] let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders return Alamofire.Manager( configuration: configuration, serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies) ) }() 

Mi enfoque para https autofirmado. El ServerTrustPolicyManager es una class open , y su function serverTrustPolicy está open . Entonces puede ser anular.

En mi caso, la list de serveres crecerá en el futuro. Si codifico la list https, necesitaré mantener la list cuando agregue un nuevo server https. Entonces, decido anular la class ServerTrustPolicyManager para satisfacer mis necesidades.

 // For Swift 3 and Alamofire 4.0 open class MyServerTrustPolicyManager: ServerTrustPolicyManager { // Override this function in order to trust any self-signed https open override func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? { return ServerTrustPolicy.disableEvaluation } } 

Entonces,

  let trustPolicies = MyServerTrustPolicyManager(policies: [:]) let manager = Alamofire.SessionManager(configuration: sessionConfig, delegate: SessionDelegate(), serverTrustPolicyManager: trustPolicies) 

Para swift 4:

 private static var Manager : Alamofire.SessionManager = { // Create the server trust policies let serverTrustPolicies: [String: ServerTrustPolicy] = [ "your domain goes here": .disableEvaluation ] // Create custom manager let configuration = URLSessionConfiguration.default configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders let man = Alamofire.SessionManager( configuration: URLSessionConfiguration.default, serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies) ) return man }() 

Entonces lo llamas así:

 Manager.upload(body.data(using: .utf8)!, to: url, method: .post, headers: headers) 

Créditos a Cnoon