C2ebef6bb95812875526978747894dd0
Alamofire(7)— 安全认证

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


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


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

HTTP特点

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

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

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

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

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

正是因为这些特点,也造就了灵活的http 存在很多问题

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

对称加密&非对称加密

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

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

缺点:对称加密的缺点就在于如果秘钥要是泄露,这样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数据 获取信息
top Created with Sketch.