ASP.NET Core 中的目的字串

取用 IDataProtectionProvider 的元件必須將唯一目的參數傳遞至 CreateProtector 方法。 目的參數是資料保護系統的安全性所既有的,因為它提供密碼編譯取用者之間的隔離,即使根密碼編譯金鑰相同也一樣。

當取用者指定目的時,目的字串會與根密碼編譯金鑰搭配使用,以衍生該取用者唯一的密碼編譯子機碼。 這會隔離取用者與應用程式中所有其他密碼編譯取用者:沒有其他元件可以讀取其承載,而且無法讀取任何其他元件的承載。 此隔離也使針對該元件所有類別的攻擊變得不可行。

Purpose Diagram Example

在上圖中,IDataProtector 執行個體 A 和 B 無法讀取彼此的承載,只能讀取自己的承載。

目的字串不一定是秘密。 它應該只是唯一的,因為沒有任何其他表現良好的元件會提供相同目的字串。

提示

使用取用資料保護 API 之元件的命名空間和類型名稱,是良好的經驗法則,因為實際上這項資訊永遠不會衝突。

負責挖掘持有人權杖的 Contoso 撰寫元件,可能會使用 Contoso.Security.BearerToken 作為其目的字串。 或者,它可能會使用 Contoso.Security.BearerToken.v1 作為其目的字串會更好。 附加版本號碼可讓未來的版本使用 Contoso.Security.BearerToken.v2 做為其目的,而且就承載而言,不同的版本會完全彼此隔離。

由於 CreateProtector 的目的參數是字串陣列,因此上述參數可以改指定為 [ "Contoso.Security.BearerToken", "v1" ]。 這可建立目的階層,並開啟使用資料保護系統的多租用戶案例的可能性。

警告

元件不應允許不受信任的使用者輸入成為目的鏈結的唯一輸入來源。

例如,請考量負責儲存安全訊息的 Contoso.Messaging.SecureMessage 元件。 如果安全傳訊元件要呼叫 CreateProtector([ username ]),惡意使用者可能會建立一個使用者名稱為「Contoso.Security.BearerToken」的帳戶,以嘗試讓元件呼叫 CreateProtector([ "Contoso.Security.BearerToken" ]),因此無意中導致安全傳訊系統產生可能被視為驗證權杖的承載。

傳訊元件較佳的目的鏈結是 CreateProtector([ "Contoso.Messaging.SecureMessage", $"User: {username}" ]),可提供適當的隔離。

IDataProtectionProviderIDataProtector 和目的所提供的隔離行為如下:

  • 對於指定的 IDataProtectionProvider 物件,CreateProtector 方法將建立一個唯一繫結到建立它的 IDataProtectionProvider 物件,和傳遞到該方法目的參數的 IDataProtector 物件。

  • 目的參數不得為 Null。 (如果將目的指定為陣列,這表示陣列不得為零長度,而且陣列的所有元素都必須非 Null。)空字串目的技術上是允許的,但不建議使用。

  • 如果而且僅有當兩個目的引數包含相同順序的相同字串 (使用序數比較子) 時,則兩個目的引數是相等的。 單一目的引數相當於對應的單一元素目的陣列。

  • 兩個 IDataProtector 物件只有在使用對等目的參數的對等 IDataProtectionProvider 物件建立時,才會相等。

  • 針對指定的 IDataProtector 物件,只有在對等 IDataProtector 物件的 protectedData := Protect(unprotectedData) 時,對 Unprotect(protectedData) 的呼叫才會傳回原始 unprotectedData

注意

我們不考慮某些元件刻意選擇已知與另一元件衝突的目的字串情況。 這類元件基本上會被視為惡意,而且在惡意程式碼已在背景工作處理序內執行時,此系統不打算提供安全性保證。