web-dev-qa-db-ja.com

自己署名証明書を使用したAlamofire / ServerTrustPolicy

Alamofireを使用して、自己署名証明書を使用したhttps接続でサーバーと通信します。私の環境はローカルホストで実行されます。接続しようとしましたが、応答は常に次のようになります。

Success: false
Response String: nil

私は次のコードでそれをやった:

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

}

このbashの行を使用して、サーバー側の証明書を作成しました。

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

何が間違っているのか分かりません。ヘルプは素晴らしいでしょう。

###更新###

これがcURLリクエストです。私の意見では、問題はありませんか、それとも間違っていますか?

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

返事遅れてすみません。 2つのdebugPrintsは次のとおりです。

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"

結果debugPrint:

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

### Update 3 ###

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

port辞書を作成するときに、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)
    )
}()
15
cnoon

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

次に、次のように呼び出します。

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

クレジットから正午

8
William Kinaan

時間が経ちましたが、まったく同じ問題がありました。そして、私は上記の答えを持つ解決策を見つけました。 trustPoliciesに2つのことを追加する必要がありました。

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

また、Info.plistで以下を追加する必要がありました。

<key>AppTransportSecurity</key>
<dict>
  <key>AllowsArbitraryLoads</key>
      <true/>
</dict>
2
M. Wojcik

自己署名httpsに対する私のアプローチ。 ServerTrustPolicyManageropenクラスであり、serverTrustPolicy関数もopenです。そのため、オーバーライドできます。

私の場合、サーバーリストは将来的に大きくなります。 httpsリストをハードコーディングした場合、新しいhttpsサーバーを追加するときにリストを維持する必要があります。そこで、必要に応じてServerTrustPolicyManagerクラスをオーバーライドすることにしました。

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

次に、

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