https相关
先推荐博主用OC实现的https通信:
iOS开发 - 用AFNetworking实现https单向验证,双向验证
http://blog.csdn.net/codingfire/article/details/53419521
本文信息来源于http://www.hangge.com/blog/cache/detail_1052.html,不错的一个网址。
实现了OC的https,那么swift的https怎么来写呢,实际上,两者实现没有什么差别,只是对应代码转化成swift的模式,偶然想到这个问题,但是又懒得自己去写,所以在网上找了下,于是发现了上面的网址,swift通过Alamofire实现https,由于之前遇到太多垃圾代码,为了保证这里的代码切实可行,遂通过实战来进行检验:
https双向验证:
import UIKit import Alamofire class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //认证相关设置 let manager = SessionManager.default manager.delegate.sessionDidReceiveChallenge = { session, challenge in //认证服务器证书 if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { print("服务端证书认证!") let serverTrust:SecTrust = challenge.protectionSpace.serverTrust! let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0)! let remoteCertificateData = CFBridgingRetain(SecCertificateCopyData(certificate))! let cerPath = Bundle.main.path(forResource: "server", ofType: "cer")! let cerUrl = URL(fileURLWithPath:cerPath) let localCertificateData = try! Data(contentsOf: cerUrl) if (remoteCertificateData.isEqual(localCertificateData) == true) { let credential = URLCredential(trust: serverTrust) challenge.sender?.use(credential, for: challenge) return (URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!)) } else { return (.cancelAuthenticationChallenge, nil) } } //认证客户端证书 else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate { print("客户端证书认证!") //获取客户端证书相关信息 let identityAndTrust:IdentityAndTrust = self.extractIdentity(); let urlCredential:URLCredential = URLCredential( identity: identityAndTrust.identityRef, certificates: identityAndTrust.certArray as? [AnyObject], persistence: URLCredential.Persistence.forSession); return (.useCredential, urlCredential); } // 其它情况(不接受认证) else { print("其它情况(不接受认证)") return (.cancelAuthenticationChallenge, nil) } } //数据请求 Alamofire.request("请求地址") .responseString { response in print(response) } } //获取客户端证书相关信息 func extractIdentity() -> IdentityAndTrust { var identityAndTrust:IdentityAndTrust! var securityError:OSStatus = errSecSuccess let path: String = Bundle.main.path(forResource: "client", ofType: "p12")! let PKCS12Data = NSData(contentsOfFile:path)! let key : NSString = kSecImportExportPassphrase as NSString let options : NSDictionary = [key : "xxxxxxxxxxx"] //客户端证书密码 //create variable for holding security information //var privateKeyRef: SecKeyRef? = nil var items : CFArray? securityError = SecPKCS12Import(PKCS12Data, options, &items) if securityError == errSecSuccess { let certItems:CFArray = items as CFArray!; let certItemsArray:Array = certItems as Array let dict:AnyObject? = certItemsArray.first; if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> { // grab the identity let identityPointer:AnyObject? = certEntry["identity"]; let secIdentityRef:SecIdentity = identityPointer as! SecIdentity! print("\(identityPointer) :::: \(secIdentityRef)") // grab the trust let trustPointer:AnyObject? = certEntry["trust"] let trustRef:SecTrust = trustPointer as! SecTrust print("\(trustPointer) :::: \(trustRef)") // grab the cert let chainPointer:AnyObject? = certEntry["chain"] identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray: chainPointer!) } } return identityAndTrust; } //定义一个结构体,存储认证相关信息 struct IdentityAndTrust { var identityRef:SecIdentity var trust:SecTrust var certArray:AnyObject } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
接着需要配置plist,这里的配置和OC是一样的:
配置好之后运行项目,可拿到请求结果。
Demo下载放在最后!
https单向验证,验证服务器通过服务器的域名和IP地址来验证,服务器验证客户端证书和密码:
import UIKit import Alamofire class ViewController: UIViewController { //自签名网站地址 let selfSignedHosts = ["域名","IP地址"] override func viewDidLoad() { super.viewDidLoad() //认证相关设置 let manager = SessionManager.default manager.delegate.sessionDidReceiveChallenge = { session, challenge in //认证服务器(这里不使用服务器证书认证,只需地址是我们定义的几个地址即可信任) if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust && self.selfSignedHosts.contains(challenge.protectionSpace.host) { print("服务器认证!") let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!) return (.useCredential, credential) } //认证客户端证书 else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate { print("客户端证书认证!") //获取客户端证书相关信息 let identityAndTrust:IdentityAndTrust = self.extractIdentity(); let urlCredential:URLCredential = URLCredential( identity: identityAndTrust.identityRef, certificates: identityAndTrust.certArray as? [AnyObject], persistence: URLCredential.Persistence.forSession); return (.useCredential, urlCredential); } // 其它情况(不接受认证) else { print("其它情况(不接受认证)") return (.cancelAuthenticationChallenge, nil) } } //数据请求 Alamofire.request("https://xxxxxxxxx") .responseString { response in print(response) } } //获取客户端证书相关信息 func extractIdentity() -> IdentityAndTrust { var identityAndTrust:IdentityAndTrust! var securityError:OSStatus = errSecSuccess let path: String = Bundle.main.path(forResource: "client", ofType: "p12")! let PKCS12Data = NSData(contentsOfFile:path)! let key : NSString = kSecImportExportPassphrase as NSString let options : NSDictionary = [key : "xxxxxxxxxxx"] //客户端证书密码 //create variable for holding security information //var privateKeyRef: SecKeyRef? = nil var items : CFArray? securityError = SecPKCS12Import(PKCS12Data, options, &items) if securityError == errSecSuccess { let certItems:CFArray = items as CFArray!; let certItemsArray:Array = certItems as Array let dict:AnyObject? = certItemsArray.first; if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> { // grab the identity let identityPointer:AnyObject? = certEntry["identity"]; let secIdentityRef:SecIdentity = identityPointer as! SecIdentity! print("\(identityPointer) :::: \(secIdentityRef)") // grab the trust let trustPointer:AnyObject? = certEntry["trust"] let trustRef:SecTrust = trustPointer as! SecTrust print("\(trustPointer) :::: \(trustRef)") // grab the cert let chainPointer:AnyObject? = certEntry["chain"] identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray: chainPointer!) } } return identityAndTrust; } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } } //定义一个结构体,存储认证相关信息 struct IdentityAndTrust { var identityRef:SecIdentity var trust:SecTrust var certArray:AnyObject }
同样,这里也需要配置plist,和上面双向验证是一样的。而下面这样也是可以的。
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
最后下载Demo福利,因为证书密钥等等属于机密,所以博主删除了,倒入自己的即可。