网络请求库使用Alamofire
class ABCSessionDelegate: SessionDelegate {
override func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
switch challenge.protectionSpace.authenticationMethod {
case NSURLAuthenticationMethodClientCertificate:
guard let file = Bundle.main.path(forResource: "公钥文件名", ofType: "p12"),
let p12Data = try? Data.init(contentsOf: URL.init(fileURLWithPath: file)!) else {
completionHandler(.performDefaultHandling, nil)
return
}
let p12Contents = PKCS12(pkcs12Data: p12Data, password: "公钥密码")
guard let identity = p12Contents.identity else {
completionHandler(.performDefaultHandling, nil)
return
}
let credential = URLCredential(identity: identity,
certificates: nil,
persistence: .none)
challenge.sender?.use(credential, for: challenge)
completionHandler(.useCredential, credential)
default:
completionHandler(.performDefaultHandling, nil)
}
}
private class PKCS12 {
let label: String?
let keyID: NSData?
let trust: SecTrust?
let certChain: [SecTrust]?
let identity: SecIdentity?
/// Creates a PKCS12 instance from a piece of data.
/// - Parameters:
/// - pkcs12Data: the actual data we want to parse.
/// - password: The password required to unlock the PKCS12 data.
public init(pkcs12Data: Data, password: String) {
let importPasswordOption: NSDictionary
= [kSecImportExportPassphrase as NSString: password]
var items: CFArray?
let secError: OSStatus
= SecPKCS12Import(pkcs12Data as NSData,
importPasswordOption, &items)
guard secError == errSecSuccess else {
if secError == errSecAuthFailed {
NSLog("Incorrect password?")
}
fatalError("Error trying to import PKCS12 data")
}
guard let theItemsCFArray = items else { fatalError() }
let theItemsNSArray: NSArray = theItemsCFArray as NSArray
guard let dictArray
= theItemsNSArray as? [[String: AnyObject]] else {
fatalError()
}
func f<T>(key: CFString) -> T? {
for dict in dictArray {
if let value = dict[key as String] as? T {
return value
}
}
return nil
}
self.label = f(key: kSecImportItemLabel)
self.keyID = f(key: kSecImportItemKeyID)
self.trust = f(key: kSecImportItemTrust)
self.certChain = f(key: kSecImportItemCertChain)
self.identity = f(key: kSecImportItemIdentity)
}
}
}
使用
class ABCRequest {
lazy var session : Session = {
// 验证服务器的公钥
// 默认获取了 cer 结尾的文件,不需要显示指定
let trustManager = ServerTrustManager(evaluators: [
M_NodeServerUrl: PublicKeysTrustEvaluator()
])
return Session(delegate: WSSessionDelegate(),
serverTrustManager: trustManager)
}()
session.request(url,
method: .post,
parameters: parameters,
encoding: URLEncoding.default,
headers: HTTPheaders,
interceptor: interceptor,
requestModifier: requestModifier)
}
参考资料:https://leenarts.net/2020/02/28/client-certificate-with-urlsession-in-swift/
网友评论