Alamofire(7)— 安全认证

😊😊😊Alamofire专题目录,欢迎及时反馈交流 😊😊😊html


Alamofire 目录直通车 --- 和谐学习,不急不躁!编程


这个篇章会介绍 http 安全认证相关知识!http 提供了一系列的技术和机器,可用来跟踪身份,进行安全性检测,控制对内容的访问。经过这一篇文章你会对知道为何https如此重要。同时也会介绍 Alamofire 关于安全认证的处理api

HTTP特色

  • 1️⃣.支持客户/服务器模式。浏览器

  • 2️⃣.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法经常使用的有 GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不一样。因为HTTP协议简单,使得HTTP服务器的程序规模小,于是通讯速度很快。安全

  • 3️⃣.灵活:HTTP 容许传输任意类型的数据对象。正在传输的类型由Content-Type(Content-TypeHTTP包 中用来表示内容类型的标识)加以标记。服务器

  • 4️⃣.无链接:无链接的含义是限制每次链接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开链接。采用这种方式能够节省传输时间。网络

  • 5️⃣.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺乏状态意味着若是后续处理须要前面的信息,则它必须重传,这样可能致使每次链接传送的数据量增大。另外一方面,在服务器不须要先前信息时它的应答就较快。session

正是由于这些特色,也造就了灵活的http 存在不少问题闭包

  • 通讯使用明文【没有加密过内容的】
  • 不验证通讯方身份,不管是客户端和服务器,都是随意通讯的
  • 没法证实报文的完整性【别人监听后,能够篡改】

对称加密&非对称加密

  • 1️⃣:对称加密:在对称加密当中加密使用的秘钥和解密使用的秘钥是相同的。也就是加密和解密都是同一个秘钥。这样秘钥的安全性就很是重要,秘钥是必定不能公开的

例子:假若有 ClientServer 之间要进行通信,他们商定了一种秘钥Client 用秘钥加密传输信息。Server 收到信息用秘钥解密信息。这样的一个通讯过程就是对称加密的过程。app

缺点:对称加密的缺点就在于若是秘钥要是泄露,这样Client与Server之间的信息传递就不安全了

  • 2️⃣非对称加密:有一对秘钥叫作公钥与私钥,公钥是对外公开的,全部人都能拥有,可是私钥有且只有一个。公钥和私钥都能进行加密,可是公钥加密的密文只有私钥可以解密,私钥加密的全部公钥都能解密,这就是非对称加密。

例子:假若有ClientA、ClientB、ClientC与Server进行通信,Server拥有一对公钥和私钥,它本身保留惟一的私钥,对外公开本身的公钥,这样 ClientA、ClientB、ClientC 都能拿到公钥。ClientA 用公钥加密的密文只有 Server 的私钥才能解密,这样 ClientA 传递信息就是安全的了,由于即便有中间黑客获取了公钥加密的密文,由于黑客没有私钥也没有办法解密。

缺点:非对称加密只是保证了Client向Server发送的消息是安全的,由于私钥有且只有一把在Server手中,可是反过来Server向Client发送的消息就不是安全的,由于公钥是公开的你们都能下载,也就都能解密信息。

HTTPS安全传输

超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,常称为 HTTP over TLSHTTP over SSLHTTP Secure)是一种经过计算机网络进行安全通讯的传输协议。HTTPS 经由 HTTP 进行通讯,但利用 SSL/TLS 来加密数据包。HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。

加密过程

  • 服务器把本身的公开密钥登陆至数字证书认证机构。
  • 数字证书认证机构用本身的私有密钥向服务器的公开密码署数字签名并颁发公钥证书。
  • 客户端拿到服务器的公钥证书后,使用数字签名认证机构的公开密钥,向数字证书认证机构验证公钥证书上的数字签名,以确认服务器的公开密钥的真实性。
  • 使用服务器的公开密钥对报文加密后发送。
  • 服务器用私有密钥对报文解密。

能够看到工做流程,基本分为三个阶段:

  • 1️⃣:认证服务器。浏览器内置一个受信任的CA机构 列表,并保存了这些CA机构的证书。第一阶段服务器会提供经CA机构认证颁发的服务器证书,若是认证该服务器证书的CA机构,存在于浏览器的受信任CA机构列表中,而且服务器证书中的信息与当前正在访问的网站(域名等)一致,那么浏览器就认为服务端是可信的,并从服务器证书中取得服务器公钥,用于后续流程。不然,浏览器将提示用户,根据用户的选择,决定是否继续。固然,咱们能够管理这个受信任CA机构列表,添加咱们想要信任的CA机构,或者移除咱们不信任的CA机构
  • 2️⃣协商会话密钥。客户端在认证完服务器,得到服务器的公钥以后,利用该公钥与服务器进行加密通讯,协商出两个会话密钥,分别是用于加密客户端往服务端发送数据的客户端会话密钥,用于加密服务端往客户端发送数据的服务端会话密钥。在已有服务器公钥,能够加密通信的前提下,还要协商两个对称密钥的缘由,是由于非对称加密相对复杂度更高,在数据传输过程当中,使用对称加密,能够节省计算资源。另外,会话密钥是随机生成,每次协商都会有不同的结果,因此安全性也比较高。
  • 3️⃣加密通信。此时客户端服务器双方都有了本次通信的会话密钥,以后传输的全部Http数据,都经过会话密钥加密。这样网路上的其它用户,将很难窃取和篡改客户端和服务端之间传输的数据,从而保证了数据的私密性和完整性。

Alamofire安全传输

下面咱们开始自签证书验证处理

1️⃣: 配置自签证书信息

fileprivate func lgtrustSession() -> SessionManager{
    
    let policies: [String:ServerTrustPolicy] = [
        hostUrl1: .pinCertificates(
            certificates: ServerTrustPolicy.certificates(),
            validateCertificateChain: false,
            validateHost: true),
        hostUrl2: .disableEvaluation,
        hostUrl3: .pinPublicKeys(
            publicKeys: ServerTrustPolicy.publicKeys(),
            validateCertificateChain: false,
            validateHost: true)
    ]
    
    let sesionManager = SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies))
    return sesionManager
}
复制代码
  • 参数1:certificates表明的是证书
  • 参数2:validateCertificateChain 表明是否验证证书链
  • 参数3:validateHost 表明是否验证子地址

Alamofire 安全认证策略的六种模式,其中最经常使用的有这三种:.pinCertificates 证书验证模式、.pinPublicKeys 公钥验证模式和 .disableEvaluation 不验证模式。

  • .performDefaultEvaluation 默认策略,只有合法证书才能经过验证
  • .performRevokedEvaluation 对注销证书作的一种额外设置
  • .pinCertificates 证书验证模式,表明客户端会将服务器返回的证书和本地保存的证书中的 全部内容 所有进行校验,若是正确,才继续执行。
  • .pinPublicKeys 公钥验证模式,表明客户端会将服务器返回的证书和本地保存的证书中的 PublicKey 部分 进行校验,若是正确,才继续执行。
  • .disableEvaluation 该选项下验证一直都是经过的,无条件信任。
  • .customEvaluation 自定义验证,须要返回一个布尔类型的结果。

2️⃣:证书与公钥信息获取

其中这里笔者采用的遍历整个工程 bundle 获取证书

public static func certificates(in bundle: Bundle = Bundle.main) -> [SecCertificate] {
    var certificates: [SecCertificate] = []

    let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in
        bundle.paths(forResourcesOfType: fileExtension, inDirectory: nil)
    }.joined())

    for path in paths {
        if
            let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData,
            let certificate = SecCertificateCreateWithData(nil, certificateData)
        {
            certificates.append(certificate)
        }
    }
    return certificates
}
复制代码
  • 遍历bundle 获取整个项目".cer", ".CER", ".crt", ".CRT", ".der", ".DER",而后映射拼接
  • 获取文件中data数据 获取信息
  • 公钥key也是一样的道理
public static func publicKeys(in bundle: Bundle = Bundle.main) -> [SecKey] {
    var publicKeys: [SecKey] = []

    for certificate in certificates(in: bundle) {
        if let publicKey = publicKey(for: certificate) {
            publicKeys.append(publicKey)
        }
    }
    return publicKeys
}
复制代码

3️⃣:接受质询

urlSession(
        _ session: URLSession,
        didReceive challenge: URLAuthenticationChallenge,
        completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
复制代码
  • Challenge 就是为了验证用户身份,向访问者发送一个质询,而后访问者须要提供一个正确的回答以示身份
  • URLProtectionSpace 这个表示服务器上的一块受保护的区域,访问这一块须要进行质询。他有以下经常使用属性
// realm是ProtectionSpace的标示符,
//服务器上的一组资源经过realm来标示成一组采用相同验证方式的资源(ProtectionSpace)。
open var realm: String? { get }
// 肯定此保护空间的密码是否能够安全地发送
open var receivesCredentialSecurely: Bool { get }
// 资源所在的服务器
open var host: String { get }
// 资源所在服务器端口
open var port: Int { get }
// 若是是代理,则获取此保护空间的类型
open var proxyType: String? { get }
//获取资源的协议资源
open var `protocol`: String? { get }
// 质询所采用验证方式
open var authenticationMethod: String { get }
复制代码

质询验证方式有以下几种是经常使用的

  • NSURLAuthenticationMethodHTTPBasic: HTTP基本验证,服务器向客户端询问用户名,密码
  • NSURLAuthenticationMethodClientCertificate: 客户端证书验证,服务器向客户端询客户端身份证书
  • NSURLAuthenticationMethodServerTrust: 服务器端证书验证,客户端对服务器端的证书进行验证。HTTPS中的服务器端证书验证属于这一种。

UrlCredential

他是客户端对服务器端质询的响应。根据验证方式不同,有以下几种UrlCredential:

  • 基于用户名密码的 UrlCredential
  • 基于客户端证书的 UrlCredential
  • 基于服务器端证书的 UrlCredential //就是咱们这里验证服务器端的证书要用到的
  • 它们分别对应于 UrlCredential 的三种构造方式。详情参考Apple开发文档

SecTrust

  • iOS中对证书和Accept Policy 的包装。系统对后台证书验证明际上是对该对象的验证。详情建Apple开发文档
  • 用于执行X.509证书信任评估的CFType

下面具体代码分析

if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
    let host = challenge.protectionSpace.host
    // 返回与给定主机彻底匹配的策略
    if
        let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host),
        // 返回一个SecTrustRef,它表示服务器SSL事务状态的状态
        let serverTrust = challenge.protectionSpace.serverTrust
    {
        // 评估服务器信任是否对给定主机有效。
        if serverTrustPolicy.evaluate(serverTrust, forHost: host) {
            disposition = .useCredential
            credential = URLCredential(trust: serverTrust)
        } else {
            disposition = .cancelAuthenticationChallenge
        }
    }
}
复制代码
  • 返回与给定主机彻底匹配的策略
  • 返回一个SecTrustRef,它表示服务器SSL事务状态的状态
  • 评估服务器信任是否对给定主机有效
  • 经过回调函数告诉系统对于该质询的 UrlCredential

验证方法:public func evaluate(_ serverTrust: SecTrust, forHost host: String) -> Bool

  • .performDefaultEvaluation 策略模式下

    • 建立评估SSL证书链的策略对象
    • 设置应该验证信任的策略到serverTrust
    • 调用trustIsValid开始验证匹配
  • .performRevokedEvaluation 策略模式下

    • 建立评估SSL证书链的策略对象
    • 返回用于检查证书撤销的策略对象。
    • 设置应该验证信任的策略到serverTrust,这里是一组
    • 调用trustIsValid开始验证匹配
  • .pinCertificates策略模式下

    • 若是验证证书链
      • 建立评估SSL证书链的策略对象
      • 设置应该验证信任的策略到serverTrust
      • 为给定的信任设置锚证书
      • 此外,从新启用信任锚证书,经过 SecTrustSetAnchorCertificates API
      • 调用trustIsValid开始验证匹配
    • 若是不验证证书链
      • 获取受信任的证书信息data
      • 获取当前传入的全部证书信息组
      • 匹配若是传入的证书组信息有包含受信任的证书,就返回true ,并利用outerLoop一次性直接跳出
  • .pinPublicKeys策略模式下

    • 若是验证证书链
      • 建立评估SSL证书链的策略对象
      • 设置应该验证信任的策略到serverTrust
      • 调用trustIsValid开始验证匹配
    • 若是不验证证书链
      • 匹配传入的公钥是否包含受信任公钥信息,若是包含就返回true ,并利用outerLoop一次性直接跳出
  • .disableEvaluation策略模式下

    • serverTrustIsValid = true 表示不须要验证,直接经过
  • .customEvaluation策略模式下

    • serverTrustIsValid = closure(serverTrust, host) 对外提供验证处理闭包,由用户自行提供验证策略方案

这里同时也给你们提供一篇专业介绍 证书链的文章

4️⃣:证书完毕,就能够直接正常通信了!

总结

这一篇关于 安全认证 的文章涉及到了 http以及https 各自的特色,还有加密手段,最后分析了 Alamofire安全认证,过程看是复杂,其实就是一个证书或者公钥匹配问题,可是这些也是不少iOS开发人员常常不肯去涉猎的地方,知识点枯燥难懂!可是:而世之奇伟,瑰鬼,很是之观,常在于险远,而人之所罕至焉,故非有志着不能至也。iOS中高级进阶没有其余,就是沉下心来,认真打磨本身!💪💪💪

下一篇开始介绍面向协议编程板块,最后很是感谢你们一路的关注!

就问此时此刻还有谁?45度仰望天空,该死!我这无处安放的魅力!

相关文章
相关标签/搜索