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关键词我们也刻意覆盖了原有的ICurrentUser属性,

其他同事也不需要额外的认知成本就可以开心地像往常一样使用CurrentUser属性。

吐槽一下Abp的用户和租户管理模块的更多相关文章

  1. 初识ABP vNext(7):vue身份认证管理&租户管理

    Tips:本篇已加入系列文章阅读目录,可点击查看更多相关文章. 目录 前言 开始 按钮级权限 身份认证管理 R/U权限 权限刷新 租户管理 租户切换 效果 最后 前言 上一篇介绍了vue+ABP国际化 ...

  2. ABP Zero 多租户管理

    ABPZero - 多租户管理 启用多租户 ASP.NET Boilerplate和module-zero可以运行多租户或单租户模式.多租户默认为禁用.我们可以在我们的模块PreInitialize方 ...

  3. X-Admin&ABP框架开发-租户管理

    软件即服务概念的推动,定制化到通用化的发展,用一套代码完成适应不同企业的需求,利用多租户技术可以去做到这一点.ABP里提供了多租户这一概念并且也在Zero模块中实现了这一概念. 一.多租户的概念 单部 ...

  4. Oracle12c多租户管理用户、角色、权限

    Oracle 数据库 12 c 多租户选项允许单个容器数据库 (CDB) 来承载多个单独的可插拔数据库 (PDB).那么我们如何在容器数据库 (CDB) 和可插拔数据库 (PDB)管理用户权限.背景: ...

  5. ABP理论学习之多租户

    返回总目录 本篇目录 什么是多租户 ABP中的多租户 什么是多租户 维基百科:"软件多租户是指一种软件架构,在这种软件架构中,软件的一个实例运行在服务器上并且为多个租户服务".一个 ...

  6. 详解ABP框架的多租户

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:ABP框架对多租户场景提供了很好的支持,内建了多租户的处理机制,今天我们来深入解析一下 ...

  7. 番外篇--Moddule Zero多租户管理

    番外篇--Moddule Zero多租户管理 2.1.1 关于多租户 强烈建议阅读这个文件前阅读多租户文档. 2.1.2 启用多租户 ASP.NET Boilerplate和module-zero可以 ...

  8. 分享一个基于 ABP(.NET 5.0) + vue-element-admin 管理后台

    1.前言 分享一个基于ABP(.NET 5.0) + vue-element-admin项目.希望可以降低新手对于ABP框架的学习成本,感兴趣的同学可以下载项目启动运行一下.对于想选型采用ABP框架的 ...

  9. 在vCenter5.5中为用户创建角色,管理虚拟机

    在vSphere的使用中,如有只有vCenter+ESXi节点的两级配置,为了达到多租户管理及权限分配,可以在vCenter5.5中为用户创建角色,管理虚拟机 1.以管理员身份登陆vCenter 2. ...

随机推荐

  1. 详细分析 Java 中启动线程的正确和错误方式

    目录 启动线程的正确和错误方式 前文回顾 start 方法和 run 方法的比较 start 方法分析 start 方法的含义以及注意事项 start 方法源码分析 源码 源码中的流程 run 方法分 ...

  2. Hibernate4.3基础知识2

    一.数据库的隔离级别   脏读 不可重复读 幻读 Read uncommited Y Y Y Read commited N Y Y Repeatable read N N Y Serializabl ...

  3. Centos-本机网络连接、运行端口和路由表等信息-netstat

    netstat 网络状态,显示本机网络连接.运行端口和路由表等信息 相关选项 -a 显示本机所有连接和监听端口 -n 以网络IP地址形式显示当前建立的有效连接和端口 -r 显示路由表信息 -t 显示T ...

  4. Go-注释

    什么是注释? 注释是给开发人员看的,目的是降低开发人员阅读代码的时间成本和代码阅读困难程度 Go-注释内容 1. 包注释,位于某个包下Go程序文件的顶部 2. 函数注释,位于Go函数的头部 3. 代码 ...

  5. 带着好奇心去探索IDEA

    带着好奇心去探索IDEA 工欲善其事必先利其器 软件是提高工作效率的工具.所以了解工具的特性,操作方式,能更好地使用它.一般使用掌握逻辑: 第一步:了解菜单栏-工具栏-其他窗口: 第二步:实战,真正利 ...

  6. PHP 下载七牛云的sdk

    1,语法 composer require qiniu/php-sdk 2,出现以下图片内容就是下载七牛云的sdk成功

  7. 如何解决Win7,win8无法使用DOS的Debug:

    如何解决Win7,win8无法使用DOS的Debug: 安装dosbox 将含有程序link,masm,edit,debug的文件夹masm放到d盘根目录 打开dosbox,输入mount c d:\ ...

  8. 【idea】重装系统(格式化C盘后)idea无法导入maven(jdk重装了,版本不同),结果报错!

    [以下部分截图]2019-11-25 09:48:49,045 [ 108964]   WARN -      #org.jetbrains.idea.maven - Cannot open inde ...

  9. java 图片相似度算法

     利用直方图原理实现图像内容相似度比较  ,作为笔记记录在随笔中.   public class PhotoDigest {     public static void main(String[]  ...

  10. 如何轻松使用 C 语言实现一个栈?​

    什么是数据结构? 数据结构是什么?要了解数据结构,我们要先明白数据和结构,数据就是一些int char 这样的变量,这些就是数据,如果你是一个篮球爱好者,那么你的球鞋就是你的数据,结构就是怎么把这些数 ...