吐槽一下Abp的用户和租户管理模块

1. 背景

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

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

-----------
ClaimB站: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.Uservar 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[]): 当前用户的角色. 返回当前用户角色名称的字符串数组.
.....

这里面有几个问题:

①    ICurrentUser将用户id、租户TenantId硬编码为GUID
项目原始的身份id、租户id若不为GUID,则根本不可用。
最差的情况也应该用个泛型,由应用决定特定身份片段的类型。

②      ICurrentUser 修改了IsAuthenticated的取值逻辑

  • ASP.NET Core官方认证类型不为空,就认为用户认证通过。

   // --- 来自asp.netcore源码:https://github.com/dotnet/runtime/blob/master/src/libraries/System.Security.Claims/src/System/Security/Claims/ClaimsIdentity.cspublic virtual bool IsAuthenticated{get { return !string.IsNullOrEmpty(_authenticationType); }}.....
  • Abp官方则认为UserId不为空,就认为用户认证通过。

   // ---截取自abp官方源码:Volo.Abp.Users.CurrentUserpublic class CurrentUser : ICurrentUser, ITransientDependency{private static readonly Claim[] EmptyClaimsArray = new Claim[0];public virtual bool IsAuthenticated => Id.HasValue;.....}

 ③  ICurrentUser修改了UserName的取值逻辑

  • Asp.NetCore检索声明信息中ClaimType==某个NameClaimType的Claim值, 作为身份认证卡片Identity的Name, 更灵活

  • Abp 检索声明信息中ClaimType=="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"的值,作为身份验证卡片的Name, 硬编码

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

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

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

在项目中就无法愉快地使用Abp ApplicationService、AbpController的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属性。


  • 学完这篇依赖注入,与面试官扯皮就没有问题了。

  • 我又踩坑了!如何为HttpClient请求设置Content-Type标头?

  • 临近年关,修复ASP.NET Core因浏览器内核版本引发的单点登录故障

  • 手撕公司SSO登录原理

  • 实战解读ASP.NET Core身份认证

  • ASP.NET Core应用注意这一点,CTO会对你刮目相看

- END -

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307167.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

后端学习 - JDBC

文章目录一 JDBC概述1 Java中的数据存储技术2 什么是JDBC3 JDBC程序的编写步骤二 Java连接数据库的方式三 使用 PreparedStatement 实现 CRUD 操作1 数据库的调用的三个接口2 增Create/删Delete/改Update 操作3 查Retrieval操作4 批量插入操作四 数据库事务1 事务2 事务的 ACID…

后端学习 - JavaWeb

技术体系 文章目录一 HTML1 网页的组成部分2 HTML 概述3 HTML 标签4 常用标签5 表单与表单的提交二 CSS1 语法格式2 使用方法三 JavaScript1 概述2 与 HTML 结合的两种方式3 变量类型及特殊值4 关系、逻辑运算5 数组6 函数7 事件8 DOM (Document Object Model&#…

心想技术驱动业务,却在背道而驰

这里是Z哥的个人公众号每周五11:45 按时送达当然了,也会时不时加个餐~我的第「165」篇原创敬上大家好,我是Z哥。相信每一位真正的程序员心里都有这样一个念想:只要我的技术够牛,就能驱动业务的发展。但是往…

后端学习 - SpringMVC

文章目录一 SpringMVC 简介1 MVC2 SpringMVC3 创建第一个 SpringMVC 项目二 RequestMapping1 注解类与方法的区别2 value 属性3 method 属性4 params 属性5 headers 属性6 SpringMVC 支持路径中的占位符三 获取 Request 的一系列参数1 通过控制器方法的形参2 控制器方法形参 映…

hbase shell远程连接_hbase与phoenix集成

Phoenix是构建在HBase之上的关系型数据库层,作为内嵌的客户端JDBC驱动用以对HBase中的数据进行低延迟访问Phoenix会将用户编写的sql查询编译为一系列的scan操作,最终产生通用的JDBC结果集返回给客户端Phoenix可以看成是mysql准备安装包apache-phoenix-4.…

对精致码农大佬的 [理解 volatile 关键字] 文章结论的思考和寻找真相

一:背景1. 讲故事昨天在园里的编辑头条看到 精致码农大佬 写的一篇题为:[C#.NET 拾遗补漏]10:理解 volatile 关键字 (https://www.cnblogs.com/willick/p/13889006.html) 的文章,大概就是说在 多线程环境下,一个在debu…

后端学习 - SpringBoot

SpringBoot 是整合 Spring 技术栈的一站式框架,是简化 Spring 技术栈的快速开发脚手架约定大于配置 文章目录一 概述1 第一个 SpringBoot 项目2 SpringBoot 特性:依赖管理3 SpringBoot 特性:自动配置二 SpringBoot 的 IOC容器1 组件添加&…

centos rpm 安装 perl_Linux【常用软件安装篇】

摘要:本文介绍Linux常用的软件安装方式以及jdk、vim、mysql、tomcat、redis的安装过程。1 Linux常用软件安装方式常用方式有:rmp包安装、yum指令安装、源码包安装、解压免安装。1.1 rpm包安装rpm是Red-Hat Package Manager(RPM软件包管理器&a…

日计不足涓滴成河-自定义响应结果格式化器

什么是响应结果响应结果就是,在客户端向服务器发出请求后,服务器根据客户端的请求参数,给出的结果,这就是一个完整的响应结果过程。响应的结果包含的内容非常多,主要的有 HTTP Status Code,Content-Type,Co…

docker 容器启动顺序_Docker容器启动时初始化Mysql数据库

1. 前言 Docker在开发中使用的越来越多了,最近搞了一个Spring Boot应用,为了方便部署将Mysql也放在Docker中运行。那么怎么初始化 SQL脚本以及数据呢? 我这里有两个传统方案。 第一种方案是在容器启动后手动导入,太low了不行。第二…

后端学习 - JVM(上)内存与垃圾回收

JVM 架构图 文章目录一 JVM 简介二 类加载子系统:1 作用2 类的三个加载过程3 类加载器的分类4 双亲委派机制 & Tomcat为何不遵循5 两个 class 对象为同一个类的必要条件三 运行时数据区:PC寄存器(Program Counter Register)四…

SM2 国密算法被 Linux 内核社区接受

喜欢就关注我们吧!10 月 25 日,有开发者发文称,SM2 国密算法终于被 Linux 内核社区接受了。该作者表示,SM2 的补丁已经更新到了 v7 版本,这个版本的补丁最终被社区接受,目前已经合并到了 Linux 主线的 5.10…

后端学习 - MyBatis

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的 持久层框架 文章目录一 基于配置文件的 MyBatis 搭建1 搭建过程(增删改)2 查询操作3 特殊操作二 MyBatis 获取参数值的方式1 单个字面量类型的参数2 多个字面量类型的参数3 Map 类型的参数4 实体…

国产操作系统发展离不开人才和市场

日前,中国 1024 程序员节盛大举行,一大批开源大咖齐聚千年岳麓,围绕开源标准、生态、人才发展等主题分享,共议开源软件与操作系统未来。其中,统信软件总经理刘闻欢表示,“有了市场才会被真正的用起来”&…

后端学习 - Redis

文章目录一 Redis 概述Redis 为什么是单线程,单线程为什么这么快?数据存储结构二 常用数据类型1 String2 HashHash 的扩容机制:渐进式 rehash*3 List4 Set5 Zset三 Redis 事务1 乐观锁与 watch 命令2 事务的三个特性四 Redis 持久化1 RDB(Red…

再被补刀!Flash又遭抛弃,你会怀念它吗?

喜欢就关注我们吧!微软近日发布通知,称更新了关于 Adobe Flash Player 的删除。微软更新目录站点可下载更新 KB4577586,用于删除 Flash Player。此更新适用于所有受支持的操作系统版本。重要版本 Windows 10 和 Windows 8.1 的可选更新也将在…

4位加法器的设计代码verilog_HDLBits:在线学习Verilog(六 · Problem 25-29)

本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题,并附上解答和一些作者个人的理解,相信无论是想 7 分钟精通 Verilog,还是对 Verilog 和数电知识查漏补缺的同学,都能从中有所收获。附上传送门:M…

译 | 将数据从Cosmos DB迁移到本地JSON文件

点击上方蓝字关注“汪宇杰博客”原文:Azure Tips and Tricks翻译:汪宇杰在Cosmos DB中使用数据迁移工具有一项重复的任务是将数据从一种数据库格式迁移到另一种数据库格式。我最近使用Cosmos DB作为数据库来存储Ignite大会发出的所有推文。然而一旦获得了…

在线教育后端开发项目总结

文章目录一 数据库访问接口1 MyBatis2 Spring Data JPA3 Spring Data MongoDB二 数据库1 MySQL2 MongoDB3 Redis三 开发规范化、响应格式与异常处理1 开发规范2 响应格式3 异常处理四 RabbitMQ五 Spring Cloud 相关工具1 Eureka2 Ribbon3 Feign4 Zuul 网关六 搜索服务1 Elastic…

通讯故障_掌握PLC必备知识,人机界面和 PLC 出现通讯故障如何分析解决

此次主要在阐述人机界面和 PLC 通讯时的模式状态,并列举了通讯故障实例。帮助大伙加深对这俩者的了解,掌握起来也不再是难题,解决掉拦路虎。一 台数 显 四 辊 卷 板 机PLC 控 制 系 统 核 心 与 人机界面在使用过程中,出现人机界面…