我在 Swift 2.0 上使用 Alamofire 并为我的本地服务器实现了 ServerTrustPolicy,如您在此处看到的:
let defaultManager: Alamofire.Manager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
// "localhost": .PinCertificates(
// certificates: ServerTrustPolicy.certificatesInBundle(),
// validateCertificateChain: false,
// validateHost: false
// )
"localhost": .DisableEvaluation
]
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
return Alamofire.Manager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}()
问题是当我提出请求时,无论我使用 .PinCertificates 还是 .DisableEvaluation,我总是会收到相同的错误:
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made."
UserInfo={
NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x60c00004d980>,
NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?,
_kCFStreamErrorDomainKey=3,
_kCFStreamErrorCodeKey=-9802,
NSErrorPeerCertificateChainKey=<CFArray 0x6060001498a0 [0x10bb3c7b0]>{
type = immutable, count = 1, values = (
0 : <cert(0x61600006ed80) s: localhost i: localhost>
)},
NSUnderlyingError=0x6040000ad750 {
Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)"
UserInfo={
_kCFStreamPropertySSLClientCertificateState=0,
kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x60c00004d980>,
_kCFNetworkCFStreamSSLErrorOriginalValue=-9802,
_kCFStreamErrorDomainKey=3,
_kCFStreamErrorCodeKey=-9802,
kCFStreamPropertySSLPeerCertificates=<CFArray 0x6060001498a0 [0x10bb3c7b0]>{
type = immutable, count = 1, values = (
0 : <cert(0x61600006ed80) s: localhost i: localhost>
)}
}
},
NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.,
NSErrorFailingURLKey=https://localhost:3000/auth/requestToken?auth_appId=d018ccd505db2cb1d5aacabb03fc2f3a,
NSErrorFailingURLStringKey=https://localhost:3000/auth/requestToken?auth_appId=d018ccd505db2cb1d5aacabb03fc2f3a,
NSErrorClientCertificateStateKey=0
}
我尝试使用
curl --cacert ./ca.pem https://localhost:3000
抛出的效果很好
我使用这样生成的自签名证书:
创建根 CA 私钥
openssl genrsa -out ca.key.pem 2048
自签名我的根 CA
openssl req -x509 -new -nodes -key ca.key.pem -days 1024 -out ca.crt.pem
通过生成密钥创建服务器证书,然后是 csr,然后使用 CA 对其进行签名
openssl genrsa -out server.key.pem 2048 openssl req -new -key server.key.pem -out server.csr.pem openssl x509 -req -in server.csr.pem -CA ca.crt.pem -CAkey ca.key.pem -CAcreateserial -out server.crt.pem -days 500
我使用 nodejs 的 https 模块作为我的网络服务器,我的配置如下:
require('ssl-root-cas')
.inject()
.addFile('./ca.crt.pem');
var privateKey = fs.readFileSync('./server.key.pem');
var certificate = fs.readFileSync('./server.crt.pem');
var credentials = { key: privateKey, cert: certificate };
var server = https.createServer(credentials, app);
server.listen(port);
我查看了 Alamofire 源代码,发现在委托方法中:
public func URLSession(
session: NSURLSession,
didReceiveChallenge challenge: NSURLAuthenticationChallenge,
completionHandler: ((NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void))
{
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?
if let sessionDidReceiveChallenge = sessionDidReceiveChallenge {
(disposition, credential) = sessionDidReceiveChallenge(session, challenge)
} else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
let host = challenge.protectionSpace.host
if let
serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicyForHost(host),
serverTrust = challenge.protectionSpace.serverTrust
{
if serverTrustPolicy.evaluateServerTrust(serverTrust, isValidForHost: host) {
disposition = .UseCredential
credential = NSURLCredential(forTrust: serverTrust)
} else {
disposition = .CancelAuthenticationChallenge
}
}
}
completionHandler(disposition, credential)
}
调用serverTrustPolicy.evaluateServerTrust(serverTrust, isValidForHost: host)
实际返回 true。这意味着错误可能发生在 completionHandler 代码中的某个地方,对吧?
我在处理证书方面做错了什么吗?
PS:defaultManager
没有被释放:)