2015-09-13 27 views
15

Desidero utilizzare Alamofire per comunicare con il mio server tramite una connessione https con un certificato autofirmato. Il mio ambiente funziona su localhost. Ho provato a collegare, ma la risposta per tutto il tempo si presenta così:Alamofire con un certificato autofirmato/ServerTrustPolicy

Success: false 
Response String: nil 

ho fatto con il seguente codice:

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)") 
      } 
    } 

} 

Ho creato i certificati lato server con questa linea di bash:

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

Non so cosa sto sbagliando. L'aiuto sarebbe fantastico

### Aggiornamento ###

Ecco la richiesta cURL. Secondo me, non c'è nessun problema o mi sbaglio?

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":"[email protected]","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"}] 

### Update 2 ###

Ci scusiamo per il ritardo di risposta. Qui ci sono le due DebugPrints:

Richiesta debugPrint:

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

Risultato debugPrint:

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

### Update 3 ###

Ecco l'errore completo con forse 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 occurred 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 occurred 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 
+0

si può fare con successo una richiesta utilizzando cURL? Se sì, potresti aggiungere l'esempio cURL e l'output e anche 'debugPrint' sul' result'? – cnoon

+0

Ho aggiornato il post. Non riesco a vedere alcun problema. Fai? – teawithfruit

+0

Potresti postare l'output di 'debugPrint (request)' quando 'request' è' let request = defaultManager.request (...) '. potresti pubblicare anche l'output di 'debugPrint (result)'? Senza questi, è difficile aiutare. – cnoon

risposta

12

è necessario aggiungere il dominio port quando si crea il dizionario 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) 
    ) 
}() 
+2

Grazie per la risposta. Hai ragione. Ho dimenticato di aggiungere la porta. Ma se aggiungo la porta, ottengo il seguente errore: 'Messaggio [4401: 95209] NSURLSession/NSURLConnection carico HTTP fallito (kCFStreamErrorDomainSSL, -9802)' – teawithfruit

+0

Hai forse un'altra idea? – teawithfruit

+0

Ora sembra che tu stia imbattendo in ATS. Maggiori informazioni [qui] (https://forums.developer.apple.com/thread/13472). Potresti pubblicare tutti i dettagli del nuovo errore in un aggiornamento nella domanda? – cnoon

2

Il mio approccio per https autofirmato. Il ServerTrustPolicyManager è una classe open e la funzione serverTrustPolicy è open. Quindi può essere override.

Nel mio caso, l'elenco dei server crescerà in futuro. Se faccio un hard-code dell'elenco https, dovrò mantenere l'elenco quando aggiungo un nuovo server https. Quindi, decido di ignorare la classe ServerTrustPolicyManager per soddisfare le mie esigenze.

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

Poi,

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

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

Poi si chiamano in questo modo:

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

Credits to Cnoon

1

Quindi so che è passato del tempo, ma ho avuto esattamente lo stesso problema. E ho trovato una soluzione con le risposte di cui sopra. Ho dovuto aggiungere 2 cose da trustPolicies:

let defaultManager: Alamofire.Manager = { 
    let serverTrustPolicies: [String: ServerTrustPolicy] = [ 
     // Here host with port (trustPolicy is my var where I pin my certificates) 
     "localhost:3443": trustPolicy 
     //Here without port 
     "localhost": .disableEvaluation 
    ] 

    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() 
    configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders 

    return Alamofire.Manager(
     configuration: configuration, 
     serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies) 
    ) 
}() 

Anche in Info.plist dovuto aggiungere:

<key>AppTransportSecurity</key> 
<dict> 
    <key>AllowsArbitraryLoads</key> 
     <true/> 
</dict> 
Problemi correlati