Alamofire之安全認證

在網絡如此發達的今天,網絡安全已經和每一個人息息相關了。今天咱們就一塊兒來了解一下網絡安全方面的相關知識。算法

1、HTTPS簡介

咱們知道,在HTTP協議中,發送的內容是以明文的形式傳遞的。這就致使瞭如下幾個缺陷:swift

  • 明文內容,敏感數據容易被黑客竊聽
  • 不對雙方的身份做驗證,容易被假裝
  • 沒法驗證數據的完整性,數據容易被篡改

爲了解決上面👆幾個缺陷,蘋果官方推薦使用HTTPS傳輸協議。瀏覽器

HTTPS協議是由SSL/TLS+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議。重要的是比HTTP更安全。安全

2、密碼學基礎

在瞭解HTTPS協議以前,咱們須要先有一點密碼學基礎。bash

明文:是指未被加密過的原始數據
複製代碼
密文:明文被某個加密方式(算法)加密後,就變成了密文。密文能夠被解密獲得明文
複製代碼
密鑰:是在明文轉換爲密文的算法中所使用的參數。
密鑰分爲對稱密鑰和非對稱密鑰。分別對應對稱加密和非對稱加密。
複製代碼
對稱加密:對稱加密又叫作私鑰加密,即信息的發送方和接收方使用同一個密鑰去加密和解密數據。
複製代碼

對稱加密的特色是算法公開、加密和解密速度快,適合於對大數據量進行加密。服務器

對稱加密加密過程:明文 + 加密算法 + 私鑰 => 密文 對稱加密解密過程:密文 + 解密算法 + 私鑰 => 明文網絡

非對稱加密:非對稱加密也叫作公鑰加密。非對稱加密使用一對密鑰,即公鑰和私鑰,且兩者成對出現。用公鑰或私鑰中的任何一個進行加密,用另外一個進行解密。
複製代碼

非對稱加密的缺點是加密和解密花費時間長、速度慢,只適合對少許數據進行加密。session

被公鑰加密過的密文只能被私鑰解密。 加密過程:明文 + 加密算法 + 公鑰 => 密文 解密過程:密文 + 解密算法 + 私鑰 => 明文ide

被私鑰加密過的密文只能被公鑰解密。 加密過程:明文 + 加密算法 + 私鑰 => 密文 解密過程:密文 + 解密算法 + 公鑰 => 明文函數

3、HTTPS加密

非對稱加密比對稱加密更加安全,那麼HTTPS中使用的是非對稱加密嗎?不是的。https使用的是混合加密的方式。那什麼是混合加密呢?

如上圖所示,HTTPS協議在鏈接時使用的是非對稱加密。在數據傳輸過程當中,使用的是對稱加密。

由於非對稱加密速度慢,不合適在數據傳輸過程加密。因此在傳輸過程當中使用對稱加密。而爲了網絡請求的安全性,因此在鏈接過程當中使用了非對稱加密。

4、HTTPS通信過程

那麼HTTPS的通信過程是怎樣的呢?

  • 客戶端使用HTTPS的URL訪問服務器,與Web服務器創建SSL鏈接。
  • Web服務器收到客戶端請求後,會將網站的證書信息(證書中包含公鑰)傳送一份給客戶端。
  • 客戶端瀏覽器與Web服務器開始協商SSL/TLS鏈接的安全等級,也就是信息加密的等級。
  • 客戶端瀏覽器根據雙方贊成的安全等級,創建會話密鑰,而後利用網站的公鑰將會話密鑰加密,並傳送給網站。
  • Web服務器利用本身的私鑰解密出會話密鑰。
  • Web服務器利用會話密鑰加密與客戶端之間的通訊。
  • 在當前未斷開以前,客戶端向服務端發送的消息都使用會話密鑰加密,服務端再使用會話密鑰解密。

5、網絡挑戰

舉個栗子🌰:

let urlBD = "https://47.105.168.156:20199/"

Alamofire.request(urlBD, method: .get, parameters: ["users": "bar"])
    .response { (response) in
        print(response)
}
複製代碼

在上面👆的栗子中,咱們向一個https地址發起了網絡請求。運行以後會發現報了一些錯誤。

TIC SSL Trust Error [1:0x600000a592c0]: 3:0
...
Task <C47E510C-D9F5-4C62-9EB0-D58FFF71A638>.<1> finished with error - code: -1202
Task <C47E510C-D9F5-4C62-9EB0-D58FFF71A638>.<1> load failed with error Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be 「47.105.168.156」 which could put your confidential information at risk."
複製代碼

根據錯誤信息,大概是說服務器的證書失效。那麼這個錯誤應該如何修復呢?想要修復這個錯誤,咱們應該知道,這個錯誤是什麼時候打印的。

咱們從錯誤信息中看到有 finished with error,那麼咱們在 didCompleteWithError 函數中斷點調試一下。

斷點後發現,在進入 didCompleteWithError 回調函數以前,已經打印了錯誤信息。因此,咱們的猜想不成立。

咱們知道,全部的網絡請求都會走 SessionDelegate 的回調。既然不在 didCompleteWithError 回調函數,那會不會在其餘回調函數呢?而後咱們就會找到這樣一個回調函數:

從註釋文檔來看,這是和證書相關的回調。咱們斷點調試一下,發現確實會來到這裏。而且會調用 delegate.urlSession 回調函數。

就是這個回調函數,並且會由於紅框中的判斷沒有成功而直接跳出執行。因此,這裏就是錯誤的關鍵,這其實就是常說的 網絡挑戰

session.serverTrustPolicyManagerURLSession 的一個關聯屬性。那它是什麼時候設置的呢? 還記得在【Alamofire之SessionManager】分析 SessionManager 初始化的時候見過這個屬性,可是當時沒有分析。

因此咱們應該在 SessionManager 的初始化時應該多一個參數 serverTrustPolicyManager

咱們自定義一個 SessionManager

func boManager() -> SessionManager {
    
    // 第一個參數是要信任的主機host
    let policies: [String: ServerTrustPolicy] = [
        "47.105.168.156": .pinCertificates(certificates: ServerTrustPolicy.certificates(), validateCertificateChain: true, validateHost: true)
    ]
    
    // 其他參數使用默認值
    let sessionManager = SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies))
    
    return sessionManager
}
複製代碼

使用 ServerTrustPolicyManager 初始化 SessionManager

ServerTrustPolicyManager 須要一個字典參數 policies。 字典的key是你認證的主機地址。value是一個枚舉 ServerTrustPolicy

枚舉 ServerTrustPolicy 有不少個case,小夥伴能夠根據文檔選擇本身的方式。這裏使用 pinCertificates 固定證書認證舉例。

須要服務器給你一個證書,放入工程中。而後再使用自定義的 SessionManager 請求網絡。

let urlBD = "https://47.105.168.156:20199/"

// 使用自定義SessionManager網絡請求
self.sessionManager = boManager()
self.sessionManager?.request(urlBD)
    .response { (response) in
        print(response)
}
複製代碼

從新運行,就會發現不會報以前的錯誤了。

若是小夥伴只是測試,或者本身寫個demo,還可使用 .disableEvaluation 不驗證證書。

// 不驗證證書
let policies: [String: ServerTrustPolicy] = [
    "47.105.168.156": .disableEvaluation
]
複製代碼

可是這樣會很危險,小夥伴們慎用。

看到這裏,不少小夥伴可能會有疑問了。由於平時咱們開發中沒有這樣設置過,都是直接網絡請求,也沒有報錯。這是由於,上面適用的狀況是自簽證書。而咱們平時更多使用的是CA證書。

那麼CA證書又是如何工做的呢?請看下圖:

以上就是本篇Alamofire安全認證的所有內容。如有不足之處,請評論指正。

相關文章
相關標籤/搜索