ASP.NET Core 基於聲明的訪問控制究竟是什麼鬼?git
聊到基於聲明的身份認證將 身份和簽發機構分離,應用程序信任簽發機構,故承認簽發的身份信息。github
-- | --- | --- | --- |
---|---|---|---|
Claim | B站:438962688 Name:飯思思_ | weibo:538210234 Name:飯思思van | 姓名:不詳 籍貫:九江 |
ClaimsIdentity | 嗶哩嗶哩帳戶 | 微博帳戶 | 身份證 |
ClaimsPrincipal |
因而咱們一般會有以下:數組
var claims = new[] { new Claim(nameof(ClaimTypes.NameIdentifier),_authData.Data["userId"].ToString(),ClaimValueTypes.String), new Claim(nameof(ClaimTypes.Name),_authData.Data["userName"].ToString(),ClaimValueTypes.String), new Claim("profileId",_authData.Data["profileId"].ToString()), new Claim("positionId",_authData.Data["positionId"].ToString()), new Claim("organizationId",_authData.Data["organizationId"].ToString()), new Claim("maxAge",_authData.Data["maxAge"].ToString()), }; // 設置身份卡片內容 、身份卡片核心Name, 這個時候HttpContext.User var identity = new ClaimsIdentity(claims, Scheme.Name,nameof(ClaimTypes.Name),nameof(ClaimTypes.Role)); Context.User = new ClaimsPrincipal(identity);
咱們如今能夠在Action中使用 HttpContext.User.Identity 獲取聲明的身份信息。框架
當我滿心歡喜在Abp vnext中封裝的ICurrentUser接口
獲取身份信息,卻沒法獲取身份信息。asp.net
ICurrentUser 封裝了身份信息,用於獲取有關當前活動的用戶信息,已經被Abp框架默認注入。
你會在ApplicationSerive、 AbpController看到只讀屬性CurrentUser, 在Abp服務和控制器中是能夠即時使用的。ide
--- | --- |
---|---|
| |學習
AbpICurrentUser
獲取不到常規HttpContext.User信息,是由於使用了特定的封裝,封裝的方式我不能苟同:ui
如下是 ICurrentUser 接口的基本屬性: IsAuthenticated 若是當前用戶已登陸(已認證),則返回 true. 若是用戶還沒有登陸,則 Id 和 UserName 將返回 null. Id (Guid?): 當前用戶的Id,若是用戶未登陸,返回 null. UserName (string): 當前用戶的用戶名稱. 若是用戶未登陸,返回 null. TenantId (Guid?): 當前用戶的租戶Id. 對於多租戶 應用程序頗有用. 若是當前用戶未分配給租戶,返回 null. Email (string): 當前用戶的電子郵件地址. 若是當前用戶還沒有登陸或未設置電子郵件地址,返回 null. Roles (string[]): 當前用戶的角色. 返回當前用戶角色名稱的字符串數組. .....
這裏面有幾個問題:編碼
ICurrentUser將用戶id、租戶TenantId硬編碼爲GUID
底層產生的身份id、租戶id若不爲GUID,則根本不可用。
最差的狀況也應該用個泛型,由應用決定特定身份片斷的類型。.net
ICurrentUser 修改了IsAuthenticated
的取值邏輯:
認證類型不爲空
,就認爲用戶認證經過。// --- 來自asp.netcore源碼:https://github.com/dotnet/runtime/blob/master/src/libraries/System.Security.Claims/src/System/Security/Claims/ClaimsIdentity.cs public virtual bool IsAuthenticated { get { return !string.IsNullOrEmpty(_authenticationType); } } .....
UserId不爲空
,就認爲用戶認證經過。// ---截取自abp官方源碼:Volo.Abp.Users.CurrentUser public class CurrentUser : ICurrentUser, ITransientDependency { private static readonly Claim[] EmptyClaimsArray = new Claim[0]; public virtual bool IsAuthenticated => Id.HasValue; ..... }
UserName
的取值邏輯:Abp 將UserId、TenantId 硬編碼爲GUID,已經不夠通用;
另外Abp強行變動了ASP.NET Core基於聲明的身份驗證的取值邏輯,若要咱們接受,須要一點學習成本。
本次個人項目就是由於UserID、TenantId爲String, 在CurrentUser中轉換失敗,Name也取值失敗。
這樣我在項目中就沒法使用Abp ApplicationService、Controller的CurrentUser只讀屬性。
個人策略,仍是向儘可能使用Abp框架,儘可能作到【對修改封閉,對擴展開放】,
因而我仿照Abp的CurrentUser實現了適合自身項目的CurrentUser
:
public class CurrentUser: ITransientDependency { private static readonly Claim[] EmptyClaimsArray = new Claim[0]; public virtual string Id => _principalAccessor.Principal?.Claims?.FirstOrDefault(c => c.Type == nameof(ClaimTypes.NameIdentifier))?.Value; public virtual string UserName => _principalAccessor.Principal?.Claims?.FirstOrDefault(c => c.Type == nameof(ClaimTypes.Name))?.Value; public virtual string Email => _principalAccessor.Principal?.Claims?.FirstOrDefault(c => c.Type == nameof(ClaimTypes.Email))?.Value; public virtual string TenantId => _principalAccessor.Principal?.Claims?.FirstOrDefault(c => c.Type == "profileId")?.Value; public virtual string[] Roles => FindClaims("roleId").Select(c => c.Value).ToArray(); private readonly ICurrentPrincipalAccessor _principalAccessor; public CurrentUser(ICurrentPrincipalAccessor principalAccessor) { _principalAccessor = principalAccessor; } public virtual Claim FindClaim(string claimType) { return _principalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == claimType); } } }
編寫繼承自ApplicationService、AbpController的通用服務類、控制器類,
new關鍵字顯式隱藏從基類繼承的成員
這樣咱們既能夠使用 Abp框架其餘能力,利用new關鍵詞咱們也刻意覆蓋了原有的 CurrentUser屬性,
其餘同事也不須要額外的認知成本就能夠開心地像往常同樣使用CurrentUser
屬性。