![](/img/trans.png)
[英]Why does System.Web.HttpContext.Current.User resolve during a controller constructor, but User.Identity does not
[英]Why does User.Identity not contain the whole list of ClaimsTypes?
我正在處理 ASP.NET Core web 應用程序。 我的 do.net 版本是 3.1.401,我使用的是 Visual Studio Community 2019 版本 16.7.2。 我正在使用沒有 ASP.NET Core Identity 的 cookie 身份驗證。 一切正常。
在我的_Layout
視圖的頁腳中,我顯示了經過身份驗證的用戶的名稱,我可以使用@User.Identity.Name
輕松訪問它。 但我也想補充他的角色。 我首先認為可以使用此@User.Identity.Role
但事實並非如此。
以下是成功登錄后創建的聲明列表:
Admin loggedAdmin = form.LoginCheck();
if (loggedAdmin != null)
{
if (!loggedAdmin.Deleted || !loggedAdmin.IsActive)
{
string name = StringCustomMethods.GetInitialsFromFirstName(loggedAdmin.FName) + loggedAdmin.LName;
var userClaims = new List<Claim>()
{
new Claim(ClaimTypes.Name, name),
new Claim(ClaimTypes.Role, loggedAdmin.Role),
new Claim("Id", loggedAdmin.Id.ToString()),
new Claim("RoleType", loggedAdmin.Role), <---- created to access it easily
};
// Passes list of claims and AuthenticationTypes
var claimsListAndAuthTypes = new ClaimsIdentity(userClaims, "User Identity");
// etc...
然后我在列表中創建了一個新的 Claim,它的字符串類型可以使用它: @Context.User.FindFirst("RoleType").Value
我認為這很愚蠢,因為我已經有了ClaimTypes.Role
的聲明。 但這是我找回它的唯一簡單方法。 但也許我還缺少另一種“簡單方法”。 我是初學者...
另一個問題是為什么只能通過"@User.Identity..."
訪問Name
、 IsAuthenticated
和AuthenticationType
屬性。 最后,有一個內置聲明列表,您可以使用這些聲明並將其添加到ClaimsPrincipal
,因此您可以像上述 3 個一樣訪問它們。
謝謝
ClaimsIdentity
允許配置其默認聲明類型NameClaimType
和RoleClaimType
,然后由框架的不同部分用作處理聲明值的快捷方式。
這些快捷方式之一是ClaimsIdentity.Name
,它只返回聲明類型為配置的默認NameClaimType
的第一個身份聲明的值。 另一個快捷方式是ClaimsPrincipal.IsInRole
,它檢查身份是否具有具有指定值的RoleClaimType
類型的聲明。
這些可配置的名稱和角色聲明類型背后的想法是,沒有一種標准聲明類型適用於每一種聲明類型。 例如,對於名稱,您可能希望使用ClaimTypes.Name
(值為"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
)或ClaimTypes.NameIdentifier
(值為是"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"
)。
如果您有一個與其他非 Microsoft 平台集成的系統,您可能希望堅持使用更簡單的JWT 聲明類型。 在那里,您可以使用聲明類型"name"
或"preferred_username"
。 同樣,在某些設置中,角色聲明類型可能只是"role"
。
所以基本上,索賠類型並沒有真正標准化,您可能必須在不同的應用程序和場景中選擇不同的類型。 沒關系。 但是因為 .NET 類型中有一些實用程序,如果您希望這些實用程序正常工作,您可能必須指定您正在使用的名稱和角色聲明類型。
至於聲明的檢索,正如您自己所見,您可以訪問的不僅僅是屬性。 相反,有一些實用方法允許您查詢聲明。 最常見的是ClaimsPrincipal.FindFirst
,它返回特定類型的第一個聲明。 如果您只想檢查是否存在,您也可以使用ClaimsPrincipal.HasClaim
。
在 ASP.NET Core 中,您還擁有非常有用的擴展方法ClaimsPrincipal.FindFirstValue
,它將只返回特定聲明類型的聲明值。 這可能是您大部分時間會使用的。
作為個人建議,我還會考慮在ClaimsPrincipal
上創建您自己的一組特定於應用程序的擴展方法,它允許您直接檢索特定於您的應用程序的聲明類型的值。 這也將使您能夠直接將聲明值解析為您想要的任何類型(因為聲明僅基於字符串)。 這可能看起來像這樣:
public static class ClaimsPrincipalExtensions
{
public static string GetName(this ClaimsPrincipal user)
=> user.FindFirstValue(ClaimTypes.Name);
public static string GetRole(this ClaimsPrincipal user)
=> user.FindFirstValue(ClaimTypes.Role);
public static int GetId(this ClaimsPrincipal user)
=> int.Parse(user.FindFirstValue("id"));
}
然后,您可以直接在整個 ASP.NET Core 中存在的User
object 上使用這些擴展方法,例如在視圖或控制器中:
<div class="user-info">
<strong>@User.GetName() (@User.GetId())</strong>
Current role: @User.GetRole()
</div>
最后一點:通常,一個身份應該能夠同時擔任多個角色。 這就是為什么框架沒有單個Role
屬性來獲取單個角色聲明值,而是為您提供一個IsInRole
方法來根據用戶所在的角色集檢查單個角色值。當然,這只是默認設置假設:如果您的應用程序僅使用單個角色值,那么將角色聲明與您只期望單個值的任何其他聲明一樣對待是完全沒問題的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.