Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/104.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 具有自签名证书/ServerTrustPolicy的Alamofire_Ios_Swift_Https_Alamofire - Fatal编程技术网

Ios 具有自签名证书/ServerTrustPolicy的Alamofire

Ios 具有自签名证书/ServerTrustPolicy的Alamofire,ios,swift,https,alamofire,Ios,Swift,Https,Alamofire,我想使用Alamofire通过https连接与我的服务器进行通信,并使用自签名证书。我的环境在本地主机上运行。我已尝试连接,但始终得到如下响应: Success: false Response String: nil Manager.upload(body.data(using: .utf8)!, to: url, method: .post, headers: headers) 我使用以下代码完成了此操作: import Foundation import UIKit import Ala

我想使用Alamofire通过https连接与我的服务器进行通信,并使用自签名证书。我的环境在本地主机上运行。我已尝试连接,但始终得到如下响应:

Success: false
Response String: nil
Manager.upload(body.data(using: .utf8)!, to: url, method: .post, headers: headers)
我使用以下代码完成了此操作:

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":"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"}]
结果打印:

$ 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"
FAILURE: Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://localhost:3443/message, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://localhost:3443/message}
####更新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
nil
$curl-i\
-H“接受语言:美国英语;q=1.0”\
-H“接受编码:gzip;q=1.0,压缩;q=0.5”\
-H“用户代理:Message/com.teawithfruit.Message(1;操作系统版本9.0(构建13A340))”\
"https://localhost:3443/message"
2015-10-17 15:10:48.346消息[25531:1001269]NSURLSession/NSURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9802)
失败:Error Domain=nsurlerdomain Code=-1200“发生SSL错误,无法与服务器建立安全连接。”UserInfo={NSURlerErrorFailingUrlPeerTrustErrorKey=,NSLocalizedRecoverysSuggestion=是否仍要连接到服务器?,kCFStreamErrorDomainKey=3,kCFStreamErrorCodeKey=-9802,NSErrorPeerCertificateChainKey={type=不可变,计数=1,值=(
0 : 
)},NSUnderlyingError=0x7fdc30064bd0{Error Domain=KCFerrorDomain=KCF网络代码=-1200“(null)”用户信息={{kCFStreamPropertySSLClientCertificateState=0,kCFStreamPropertySSLPeerTrust=,[KCFnetworkCfsstreamsLerOriginalValue=-9802,[kCFStreamErrorDomainKey=3,[kCFStreamErrorCodeKey=-9802,kCFStreamPropertySSLPeerCertificates=-9802={type=不可变,count=1,value=(
0 : 
)}}},NSLocalizedDescription=发生SSL错误,无法与服务器建立安全连接。NSErrorFailingURLKey=https://localhost:3443/message,NSErrorFailingURLStringKey=https://localhost:3443/message,NSErrorClientCertificateStateKey=0}
成功:错
响应字符串:nil

创建
服务器信任策略
词典时,需要添加
端口

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

我的自签名https方法。
ServerTrustPolicyManager
是一个
open
类,它的
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)
对于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
}()
然后你这样称呼它:

Success: false
Response String: nil
Manager.upload(body.data(using: .utf8)!, to: url, method: .post, headers: headers)

所以我知道一段时间过去了,但我遇到了完全相同的问题。我用上述答案找到了一个解决方案。我必须在信任策略中添加两件事:

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>
AppTransportSecurity
允许任意载荷

您可以使用cURL成功地发出请求吗?如果可以,您可以在
结果上添加cURL示例和输出以及
debugPrint
?我已经更新了帖子。我看不到任何问题。您可以发布
debugPrint(请求)的输出吗
request
let request=defaultManager.request(…)
时。您是否也可以发布
debugPrint(结果)的输出
?如果没有这些,很难提供帮助。很抱歉,迟到了。我已经添加了它们。谢谢你的帮助。:)嘿,你修好了吗?谢谢你的回答。你是对的。我忘了添加端口。但是如果添加端口,我会出现以下错误:
消息[4401:95209]NSURLSession/NSURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9802)
你可能有其他想法吗?现在看来你遇到了ATS。更多信息。你能在问题的更新中发布新错误的完整详细信息吗?嘿,我已经更新了问题。它看起来像是SSL错误。也许你知道些什么?谢谢你的帮助。如果我在AppDelegate中使用此解决方案,变量defaultManager w我的所有代码都可以使用吗?是否可以配置取消默认的SessionManager并继续使用Alamofire.request而不是defaultManager.request?