ASP.NET核心身份驗證簡介

身份驗證和授權之間的區別

首先,我們應該澄清這兩個安全依賴方面的區別。簡單的答案是,身份驗證是確定您的身份的過程,而授權則圍繞您可以做的事情,即權限。顯然,在您確定允許用戶執行操作之前,您需要知道他們是誰,因此在需要授權時,您還必須首先以某種方式對用戶進行身份驗證。

ASP.NET Core中的身份驗證

與ASP.NET身份相關的基本屬性在ASP.NET Core中並沒有真正改變 - 雖然它們不同,但它們應該是ASP.NET開發人員所熟悉的。例如,在ASP.NET 4.x中,有一個名為Useron 的屬性HttpContext,它是一個類型IPrincipal,表示請求的當前用戶。在ASP.NET核心有一個類似的屬性命名User,區別在於這種屬性的類型的ClaimsPrincipal,它實現了IPrincipal。

ClaimsPrincipal與ASP.NET 4.x相比,使用此舉突出了ASP.NET Core中身份驗證工作方式的根本轉變。以前,授權通常是基於角色的,因此用戶可能屬於一個或多個角色,並且應用的不同部分可能要求用戶具有特定角色才能訪問它。在ASP.NET Core中,仍然可以使用這種基於角色的授權,但這主要是出於向後兼容的原因。他們真正希望您採取的路線是

基於聲明的身份驗證。

基於聲明的身份驗證

基於聲明的身份驗證的概念在您第一次使用時可能會有點混亂,但在實踐中它可能與您已經使用的方法非常相似。您可以將聲明視為對特定身份的聲明或屬性。該語句由名稱和值組成。例如,您可以提出DateOfBirth索賠,FirstName索賠,EmailAddress索賠或IsVIP索賠。請注意,這些陳述是關於身份什麼或誰,而不是他們可以做什麼

身份本身代表一個單一的聲明,可能有許多與之相關的聲明。例如,考慮駕駛執照。這是一個包含了一些索賠的單一身份- ,FirstName,,LastName 和你被允許駕駛哪些車輛。您的護照與另一套索賠的身份不同。DateOfBirthAddress

因此,讓我們在ASP.NET Core的上下文中看一下。ASP.NET Core中的身份是一個ClaimsIdentity。該類的簡化版本可能如下所示(實際的類更大!):

public class ClaimsIdentity: IIdentity
{
public string AuthenticationType { get; }
public bool IsAuthenticated { get; }
public IEnumerable<Claim> Claims { get; }
public Claim FindFirst(string type) { /*...*/ }
public Claim HasClaim(string type, string value) { /*...*/ }

}

我已經在本大綱中展示了主要屬性,包括Claims與身份相關的所有聲明。有許多實用方法可供使用,其中Claims兩個我在這裡展示。這些在您獲得授權時非常有用,並且您正在嘗試確定特定身份是否具有Claim您感興趣的給定身份。

該AuthenticationType物業相當不言自明。在我們以前實際的例子,這可能是字符串Passport或DriversLicense,但在ASP.NET它更可能是Cookies,Bearer或Google等,這是僅僅是被用來驗證用戶,並確定與身份相關的索賠的方法。

最後,該屬性IsAuthenticated指示身份是否經過身份驗證。這似乎是多餘的 - 如果未經過身份驗證,您怎麼能擁有聲明的身份?一種情況可能是您允許訪問您網站的訪客用戶,例如購物車。您仍然擁有與該用戶關聯的身份,並且該身份可能仍然具有與其關聯的聲明,但它們將不會被身份驗證。這是一個要記住的重要區別。

作為一個輔助,在ASP.NET Core中,如果你在構造函數中創建ClaimsIdentity並提供一個AuthenticationType,那麼IsAuthenticated它將永遠是真的。因此,經過身份驗證的用戶必須始終擁有AuthenticationType,並且相反,您不能擁有具有的未經身份驗證的用戶AuthenticationType。

多重身份

希望在這一點上,您可以對索賠及其與身份的關係進行概念性處理。我在本節開頭說過,User屬性HttpContext是a ClaimsPrincipal,而不是a ClaimsIdentity,所以讓我們來看看它的簡化版本:

public class ClaimsPrincipal :IPrincipal
{
public IIdentity Identity { get; }
public IEnumerable<ClaimsIdentity> Identities { get; }
public IEnumerable<Claim> Claims { get; }
public bool IsInRole(string role) { /*...*/ }
public Claim FindFirst(string type) { /*...*/ }
public Claim HasClaim(string type, string value) { /*...*/ }
}

從這個課程中取得的重點是有一個Identities屬性可以返回IEnumerable<ClaimsIdentity>。所以單個ClaimsPrincipal可以由多個組成Identities。Identity為了實現IPrincipal接口,還有一個屬性- 在.NET Core中它只選擇第一個標識Identities。

回到我們之前的護照和駕駛執照的例子,多個身份確實有意義 - 這些文件都是身份的形式,每個都包含許多聲明。在這種情況下,是委託人,並且您有兩種形式的身份。當你擁有這兩個身份時,你作為校長繼承了你所有身份的所有要求。

考慮另一個實際例子 - 你正在乘飛機。首先,你將在預訂臺被要求證明您對您的權利要求書FirstName和LastName等幸運的是,你還記得你的護照,這是驗證這些說法,因此你收到您的登機牌一個身份,你是在用自己的方式下一步。

在保安時,您需要證明您在航班上預訂的說法。這次你需要你攜帶的其他形式的身份證明,即有FlightNumber索賠的登機牌,這樣你就可以繼續前進了。

最後,一旦您通過保安,您將前往貴賓休息室,並被要求通過VIP Number索賠證明您的VIP身份。這可以是VIP卡的形式,這將是另一種形式的身份,並將驗證所要求的索賠。如果您沒有卡,則無法提出請求的索賠,您將被拒絕訪問,因此將被要求離開並停止製作場景。

ASP.NET核心身份驗證簡介

同樣,這裡的關鍵點是主體可以具有多個身份,這些身份可以具有多個聲明,並且ClaimsPrincipal繼承其所有聲明Identities。

如前所述,基於角色的授權主要是出於向後兼容性原因,因此IsInRole如果您遵循ASP.NET Core中強調的基於聲明的身份驗證,則通常不需要該方法。在引擎蓋下,這也是使用聲明實現的,其中聲明類型默認為RoleClaimType,或ClaimType.Role。

再次考慮ASP.NET Core,可以使用多個身份和聲明來保護應用程序的不同部分,就像在機場一樣。例如,您可以使用用戶名和密碼登錄,並根據與之關聯的身份授予一組聲明,這樣您就可以瀏覽該站點。但是,假設您的應用中有一個特別敏感的部分,您希望進一步保護。這可能要求您提供其他身份以及其他相關聲明,例如使用雙因素身份驗證或要求您重新輸入密碼。這將允許當前原則具有多個身份,並承擔所有提供的身份的聲明。

創建一個新的主體

那麼現在我們已經看到了Principor如何在ASP.NET Core中工作,我們將如何實際創建一個呢?一個簡單的示例,例如您可能在正常網頁登錄中看到的可能包含類似於以下內容的代碼

public async Task<IActionResult> Login(string returnUrl = null)
{
const string Issuer = "https://gov.uk";
var claims = new List<Claim> {
new Claim(ClaimTypes.Name, "Andrew", ClaimValueTypes.String, Issuer),
new Claim(ClaimTypes.Surname, "Lock", ClaimValueTypes.String, Issuer),
new Claim(ClaimTypes.Country, "UK", ClaimValueTypes.String, Issuer),
new Claim("ChildhoodHero", "Ronnie James Dio", ClaimValueTypes.String)
};
var userIdentity = new ClaimsIdentity(claims, "Passport");
var userPrincipal = new ClaimsPrincipal(userIdentity);
await HttpContext.Authentication.SignInAsync("Cookie", userPrincipal,
new AuthenticationProperties
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
IsPersistent = false,
AllowRefresh = false
});
return RedirectToLocal(returnUrl);
}

此方法目前對聲明進行硬編碼,但顯然您將從數據庫或其他來源獲取聲明值。我們要做的第一件事就是建立一個聲明列表,用每個聲明的名稱填充一個字符串,為其值填充一個字符串,以及可選Issuer和ClaimValueType字段。的ClaimType類是其暴露了一些常見類型的權利要求的一個幫手。例如http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name,每個都是一個網址,但您不必使用網址,如上一個添加的聲明中所示。

建立完聲明後,您可以創建新的聲明ClaimsIdentity,傳入聲明列表,並指定AuthenticationType(以確保您的身份IsAuthenticated=true)。最後,您可以ClaimsPrincipal使用您的身份創建一個新的並簽署用戶。在這種情況下,我們告訴AuthenticationManager使用"Cookie"身份驗證處理程序,我們必須將其配置為我們的中間件管道的一部分。


分享到:


相關文章: