zoukankan      html  css  js  c++  java
  • 吐槽一下Abp的用户和租户管理模块

    1. 背景

    ASP.NET Core 基于声明的访问控制到底是什么鬼?

    聊到基于声明的身份认证将 身份和签发机构分离,应用程序信任签发机构,故认可签发的身份信息。

    -- --- --- ---
    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接口获取身份信息,却无法获取身份信息。

    ICurrentUser 封装了身份信息,用于获取有关当前活动的用户信息,已经被Abp框架默认注入。
    你会在ApplicationSerive、 AbpController看到只读属性CurrentUser, 在Abp服务和控制器中是可以即时使用的。

    --- ---

    | |

    2. Abp用户、租户管理

    AbpICurrentUser获取不到常规HttpContext.User信息,是因为使用了特定的封装,封装的方式我不能苟同:

    以下是 ICurrentUser 接口的基本属性:
    
    IsAuthenticated 如果当前用户已登录(已认证),则返回 true. 如果用户尚未登录,则 Id 和 UserName 将返回 null.
    Id (Guid?): 当前用户的Id,如果用户未登录,返回 null.
    UserName (string): 当前用户的用户名称. 如果用户未登录,返回 null.
    TenantId (Guid?): 当前用户的租户Id. 对于多租户 应用程序很有用. 如果当前用户未分配给租户,返回 null.
    Email (string): 当前用户的电子邮件地址. 如果当前用户尚未登录或未设置电子邮件地址,返回 null.
    Roles (string[]): 当前用户的角色. 返回当前用户角色名称的字符串数组.
    .....
    

    这里面有几个问题:

    1. ICurrentUser将用户id、租户TenantId硬编码为GUID
      底层产生的身份id、租户id若不为GUID,则根本不可用。
      最差的情况也应该用个泛型,由应用决定特定身份片段的类型。

    2. ICurrentUser 修改了IsAuthenticated的取值逻辑:

    • ASP.NET Core官方认证类型不为空,就认为用户认证通过。
        // --- 来自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); }
       }
       .....
    
    • Abp官方则认为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;
            .....
        }
    
    1. ICurrentUser修改了UserName的取值逻辑:

    Abp 将UserId、TenantId 硬编码为GUID,已经不够通用;

    另外Abp强行变更了ASP.NET Core基于声明的身份验证的取值逻辑,若要我们接受,需要一点学习成本。

    本次我的项目就是因为UserID、TenantId为String, 在CurrentUser中转换失败,Name也取值失败。

    这样我在项目中就无法使用Abp ApplicationService、Controller的CurrentUser只读属性。

    3. 针对Abp用户、租户管理的应对方法

    我的策略,还是向尽量使用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属性。

  • 相关阅读:
    自用python时间格式转换lib库代码
    如何在datetime.strptime中添加时区
    bs3迁移到bs4, import lxml.html.soupparser 报错的解决
    mac下pip install lxml报错
    删除 Mac OS 10.10 中“打开方式”里重复或无用的程序列表
    python的urllib2库详细使用说明
    近期个人项目计划
    在centos中添加freeswitch服务开机自动运行
    ddd
    Sqlserver 2008安装
  • 原文地址:https://www.cnblogs.com/JulianHuang/p/13902901.html
Copyright © 2011-2022 走看看