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度仰望天空,該死!我這無處安放的魅力!

相關文章
相關標籤/搜索