Ios 具有自签名证书/ServerTrustPolicy的Alamofire
我想使用Alamofire通过https连接与我的服务器进行通信,并使用自签名证书。我的环境在本地主机上运行。我已尝试连接,但始终得到如下响应: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
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?