​​https相关​​
先推荐博主用OC实现的https通信:
iOS开发 - 用AFNetworking实现https单向验证,双向验证

本文信息来源于​​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是一样的:

iOS开发 - swift通过Alamofire实现https通信_客户端


配置好之后运行项目,可拿到请求结果。

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福利,因为证书密钥等等属于机密,所以博主删除了,倒入自己的即可。
​​​双向认证下载​​​
​​​单向认证下载​