在這篇文章中,我將介紹ASP.NET Core 數據保護系統:它是什么,為什么我們需要它,以及它如何工作。
為什么我們需要數據保護系統?
數據保護系統是ASP.NET Core使用的一組加密api。加密必須由不受信任的第三方處理的數據。
這方面的典型例子是身份驗證cookie。cookie是在請求之間持久化狀態的一種方法。你不希望每次向服務器請求時都必須提供用戶名和密碼,這將非常麻煩!
相反,只需向服務器提供一次憑據。服務器驗證你的詳細信息,並發出一個cookie,表明“他不需要提供任何其他證明,相信他。”對於后續的請求,可以簡單地提供該cookie,而不必提供憑據。瀏覽器自動發送cookie與后續請求,這是web為用戶實現流暢登錄體驗的方式。
cookie是非常敏感的東西。任何包含cookie的請求都將被視為原始用戶發送的請求,就像原始用戶在每個請求中都提供了用戶名和密碼一樣。瀏覽器中有很多保護措施(例如CORS)來阻止攻擊者訪問這些cookie。
然而,這不僅僅是阻止別人得到你的cookie。作為一個網站所有者,你也不希望用戶篡改他們自己的cookie。
身份驗證cookie通常不僅僅包含經過身份驗證的用戶的ID或名稱。它們通常包含各種附加的要求。它包含了用戶的詳細信息。它們可以是真實數據,如名稱、電子郵件或電話號碼,但它們也可以是與權限相關的聲明,如是否是管理員或是否可以編輯。
對於每個請求,通常都需要這些,以確定是否允許用戶采取操作。通常包含在發送給用戶的身份驗證cookie中,而不是每次請求都必須從數據庫加載。
這使得應用程序更加容易——一旦通過從cookie中提取用戶主體對用戶進行身份驗證,應用程序就會確切地知道用戶擁有哪些權限。這意味着應用程序必須信任cookie。如果cookie是明文發送的,那么用戶只需編輯這些值,就會暴露應用程序中明顯的安全漏洞。
ASP.NET Core數據保護系統正是為了這個目的而使用的。它對敏感數據(如身份驗證cookie)進行加密和解密。通過在響應中返回身份驗證cookie之前對其進行加密,應用程序知道該cookie沒有被篡改,並可以信任其值。
數據保護系統如何工作?
數據保護系統試圖解決一個棘手的問題:如何保護暴露給攻擊者的敏感數據,理想情況下不向開發人員暴露任何密鑰,同時遵循加密的最佳實踐。
數據保護系統使用對稱密鑰加密來保護數據。使用包含隨機數據的密鑰加密數據,使用相同的密鑰解密數據。
在一個典型的ASP.NET Core應用程序可能有幾種不同類型的不相關數據需要加密。例如,除了身份驗證cookie之外,可能還需要加密跨站點請求偽造令牌(CSRF)或密碼重置令牌。
你可以將相同的鍵用於所有這些不同的目的,但這可能會帶來問題。例如,如果密碼重置令牌不能“意外地”(更有可能是惡意地)用作身份驗證令牌,那就好得多。
ASP.NET Core數據保護系統實現了這一目標。數據保護系統有一個不能直接使用的父密鑰。必須從父密鑰派生子密鑰,這些子密鑰用於加密和解密數據。
使用相同的purpose字符串從父密鑰派生密鑰總是會給出相同的密鑰,因此如果你擁有父密鑰並且知道purpose字符串,那么總是可以解密已加密的數據。如果密鑰是用不同的purpose導出的,那么嘗試解密數據將會失敗。這樣可以保持數據隔離,這對安全性更好。
在大多數情況下,你不必直接與數據保護系統交互來創建密鑰或加密數據。這是由ASP.NET Core核心框架及其附帶的庫處理的。它們確保在你的應用程序中為每個不同的purpose使用唯一的字符串。如果你願意,你可以創建自己的保護程序並加密其他數據(見下文),但這不是ASP.NET Core的日常運行所必需的。
我是一個.net框架開發者——這聽起來很像<machineKey>?
數據保護系統是ASP.NET Core的一個新功能。,但是保護身份驗證令牌的需要並不是新的,那么我們以前用的是什么呢?答案是<machineKey>。<machineKey>元素的使用方式與ASP.NET Core數據保護系統非常相似,配置密鑰和密碼學套件,用於通過身份驗證系統加密數據(以及其他地方)。不幸的是,使用這個密鑰時有些復雜,因為它通常是從machine.config讀取的。必須在運行應用程序的機器上配置。在集群中運行時,必須確保這些鍵保持同步,否則可能會產生問題!
在.net Framework 4.5中,我們可以替換<machineKey>元素及其使用的整個加密管道。
如何管理數據保護密鑰?
如果對安全性有所了解,那么你可能已經聽到應該定期輪換密碼、機密和證書的說法。如果你的某個秘密被泄露了,這可以在一定程度上減少影響。這就是為什么簽發HTTPS證書的壽命越來越短的原因。
根據你從框架和工具獲得的支持,更換秘鑰和證書可能會很痛苦,特別是在過渡時期,可能需要同時支持新舊秘鑰。
鑒於數據保護對於保護ASP.NET Core是至關重要的。你不會驚訝秘鑰輪換是數據保護系統的默認設置。默認情況下,數據保護的生命周期為90天,但通常不必為此擔心。當舊密鑰快要過期時,數據保護系統會自動創建新的密鑰。所有可用密鑰的集合稱為密匙環。
在這篇文章中,我不會深入密鑰管理的細節。請注意,秘鑰輪換是自動發生的,只要你不刪除任何舊的鍵(或顯式地撤銷它們),那么加密的數據仍然可以使用過期的鍵檢索。過期的密鑰不能用於加密新數據。
我是否也可以保護其他數據,還是僅用於身份驗證cookie?
數據保護系統由ASP.NET Core隱含地使用並處理認證令牌的加密和解密。它也被ASP.NET Core用來保護密碼重置和MFA令牌。你不需要為這種保護做任何事情——框架自己處理保護。
如果你有自己想要加密的臨時數據,可以直接使用數據保護api。我將在后面的文章中詳細介紹,但以下內容展示了中如何使用IDataProtectionProvider服務(默認在ASP.NET Core apps)加密和解密一些數據:
public class MyClass { // The IDataProtectionProvider is registered by default in ASP.NET Core readonly IDataProtectionProvider _rootProvider; public MyClass(IDataProtectionProvider rootProvider) { _rootProvider = rootProvider; } public void RunSample() { // Create a child key using the purpose string string purpose = "Contoso.MyClass.v1"; IDataProtector protector = provider.CreateProtector(purpose); // Get the data to protect Console.Write("Enter input: "); string input = Console.ReadLine(); // Enter input: Hello world! // protect the payload string protectedPayload = _protector.Protect(input); Console.WriteLine($"Protect returned: {protectedPayload}"); //PRINTS: Protect returned: CfDJ8ICcgQwZZhlAlTZT...OdfH66i1PnGmpCR5e441xQ // unprotect the payload string unprotectedPayload = _protector.Unprotect(protectedPayload); Console.WriteLine($"Unprotect returned: {unprotectedPayload}"); //PRINTS: Unprotect returned: Hello world } }
一般來說,這並不是你想要做的事情。我個人只在處理密碼重置和類似的令牌時需要它。
有什么是我不應該使用數據保護的嗎?
重要的一點是,數據保護系統並不是真正用於通用加密。我們希望你加密的東西,就其本質而言,有一個有限的生命周期,如身份驗證令牌和密碼重置令牌。
理論上,你可以對希望加密和長期存儲的數據(例如在數據庫中)使用數據保護系統。數據保護密鑰每90天過期一次(默認情況下),但是你仍然可以使用過期的密鑰解密數據。
如果數據保護密鑰因為某種原因被刪除,真正的危險就來了。不建議這樣做,但意外總是會發生的。如果使用正確,刪除數據保護密鑰對大多數應用程序的影響相對較小——用戶將不得不再次登錄,以前發出的密碼重置鍵將無效——這很煩人,但不會造成災難。
另一方面,如果你已經用數據保護系統加密了敏感數據,然后將其存儲在數據庫中,那么就有大問題了。那些數據都不見了,被毀了。絕對不值得冒這個險!相反,你應該使用.NET Core中的專用加密庫,以及為此目的創建的特定證書或密鑰。
如何在我的ASP.NET Core中配置數據保護?
通常,你與數據保護系統交互的唯一地方是配置它的時候,如果沒有正確地配置它,你可能會暴露於安全漏洞中,或者無法解密身份驗證cookie。
一方面,數據保護系統需要易於配置和維護,因為復雜性和維護開銷通常會導致bug或不良實踐。但ASP.NET Core還需要在各種環境下運行:Windows、Linux、macOS;在Azure, AWS;在高端服務器和樹莓派上。每個平台都有不同的內置加密機制和可用特性,而.NET Core需要在所有這些平台上都是安全的。
為了解決這個問題,數據保護系統使用了一種通用的“插件”式架構。基本上有兩個不同的可插入區域:
- 密鑰環持久性位置:密鑰應該存儲在哪里?
- 持久性加密:密鑰是否應該在靜止時加密,如果是,如何加密。
ASP.NET Core試圖在默認情況下將這些設置為合理的選項。例如,在Windows(非azure應用程序)機器上,將持久化到%LOCALAPPDATA%\ASP.net\數據加密密鑰。
不幸的是,一旦你開始在生產環境中運行應用程序並對應用程序進行擴展,大多數默認設置都將不起作用。相反,你可能需要研究一種可選的配置方法。
總結
在這篇文章中,我提供了ASP.NET Core數據保護系統的高級概述。我描述了數據保護系統的動機以及它背后的一些設計原則。
歡迎關注我的公眾號,如果你有喜歡的外文技術文章,可以通過公眾號留言推薦給我。
原文鏈接:https://andrewlock.net/an-introduction-to-the-data-protection-system-in-asp-net-core/