通过中间件添加用户的Claim

简介: 本文主要介绍 [Sang.AspNetCore.RoleBasedAuthorization](https://www.nuget.org/packages/Sang.AspNetCore.RoleBasedAuthorization) 库如何通过中间件实现对用户 `Claim` 的添加。

背景

前面我们介绍了通过对自定义授权策略和自定义授权处理程序的使用实现了基本的RBAC权限设计,将大量的用户可访问资源及操作的标识直接放到用户的 JWT Token 中显然并不合适,这篇文章我们主要介绍通过中间件如何根据用户的角色添加用户的 Claim

实现

角色获取

首先我们需要提供一个接口 IRolePermission ,需要用户自行实现 GetRolePermissionClaimsByName 通过角色名获取用户的 List<Claim>。这里当然也可将用户自身拥有的特定 Claim 也加入进去。

public interface IRolePermission
{
    /// <summary>
    /// 获取角色的所有 Permission 
    /// </summary>
    /// <param name="roleName"></param>
    /// <returns></returns>
    Task<List<Claim>> GetRolePermissionClaimsByName(string roleName);
}

中间件核心逻辑

创建中间件 RolePermissionMiddleware ,通过 DI 注入 IRolePermission rolePermission。核心的执行逻辑为:

/// <summary>
/// 自定义中间件要执行的逻辑
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task Invoke(HttpContext context)
{
}

要确保用户信息存在

if (context.User is null)
{
    await _next(context);
    return;
}

这里我们提供了一个可选的参数,使中间件可以单独使用,也可以仅在含有ResourceAttribute标记时执行。

var endpoint = context.Features.Get<IEndpointFeature>()?.Endpoint;
if (endpoint is null)
{
    await _next(context);
    return;
}
var endpointMetaData = endpoint!.Metadata;
bool hasResourceAttribute = endpointMetaData.Any(x => x is ResourceAttribute);
if (!hasResourceAttribute)
{
    await _next(context);
    return;
}

该中间件主要的核心逻辑为读取用户所有的角色,然后查询角色对应的权限将其放入。

// 获取用户的所有角色
var roles = context.User.FindAll(ClaimTypes.Role);
// 逐个获取角色的 claims 并添加给 User
foreach (var role in roles.ToList())
{
    var roleclaims = await _rolePermission.GetRolePermissionClaimsByName(role.Value);
    if (roleclaims.Count() > 0)
    {
        context.User.AddIdentity(new ClaimsIdentity(roleclaims));
    }
}

中间件注册

中间件的注册提供了可选的参数,同时需要添加用户角色查询服务。添加RolePermissionExtensions

/// <summary>
/// 添加根据角色名为 User 加入角色 Permission 的中间件
/// </summary>
/// <param name="app"></param>
/// <param name="configureOptions"></param>
/// <returns></returns>
public static IApplicationBuilder UseRolePermission(this IApplicationBuilder app, Action<RolePermissionOptions> configureOptions)
{
    var options = new RolePermissionOptions();
    configureOptions(options);
    return app.UseMiddleware<RolePermissionMiddleware>(options);
}

/// <summary>
/// 添加根据角色名为 User 加入角色 Permission 的中间件
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseRolePermission(this IApplicationBuilder app)
{
    return app.UseMiddleware<RolePermissionMiddleware>(new RolePermissionOptions());
}

/// <summary>
/// 添加角色权限查询服务
/// </summary>
/// <typeparam name="RolePermission">获取角色权限的实现</typeparam>
/// <param name="Services"></param>
public static void AddRolePermission<RolePermission>(this IServiceCollection Services) where RolePermission : class, IRolePermission
{
    Services.AddSingleton<IRolePermission, RolePermission>();
}

最后

需要特别注意的是,这个中间件启用的位置。需要在 UseAuthentication 之后 UseAuthorization 之前,也就是说要在验证了用户后,开始检查用户权限前将用户的角色权限赋予给 context.User

本文介绍的相关代码已经提供 Nuget 包,并开源了代码,感兴趣的同学可以查阅:
https://github.com/sangyuxiaowu/Sang.AspNetCore.RoleBasedAuthorization

如有错漏之处,敬请指正。

相关文章
|
运维 程序员 项目管理
一份【软件工程】的学习指南已到达,请注意查收!!
该文章提供了一份软件工程的学习指南,包括学习软件工程的重要性、基本内容概览以及建议的学习方法和路径。
一份【软件工程】的学习指南已到达,请注意查收!!
|
9月前
|
存储 运维 监控
2025年4月深度评测:10款最值得部署的网络监控软件
真正卓越的运维不仅仅是对当前问题的解决,更在于对未来的预测和防范。 OpManager 的预测报表功能可以为用户提供有关未来存储需求增长方式的直观展示,帮助用户进行基于需求的容量规划,从而避免成本浪费。
460 0
|
人工智能 自然语言处理
RWKV-7:RWKV系列开源最新的大模型架构,具有强大的上下文学习能力,超越传统的Attention范式
RWKV-7是RWKV系列的最新大模型架构版本,具有强大的上下文学习能力,超越了传统的attention和linear attention范式。本文详细介绍了RWKV-7的主要功能、技术原理及其在多语言处理、文本生成等领域的应用场景。
923 7
RWKV-7:RWKV系列开源最新的大模型架构,具有强大的上下文学习能力,超越传统的Attention范式
|
10月前
|
人工智能 供应链 搜索推荐
2025年中国快消品企业CRM选型指南
本文围绕2025年中国快消品企业CRM选型展开。快消行业数字化转型加速,CRM至关重要,但企业转型面临诸多困境。文章提出CRM选型的常规标准,并对比纷享销客、用友、勤策等五家主流服务商。
|
网络协议 Linux 应用服务中间件
kali的常用命令汇总Linux
kali的常用命令汇总linux
1166 7
|
机器学习/深度学习 数据采集 人工智能
AI在医疗:深度学习在医学影像诊断中的最新进展
【10月更文挑战第26天】近年来,深度学习技术在医学影像诊断中的应用日益广泛,通过训练大量医学影像数据,实现对疾病的准确诊断。例如,卷积神经网络(CNN)已成功用于识别肺癌、乳腺癌等疾病。深度学习不仅提高了诊断准确性,还缩短了诊断时间,提升了患者体验。然而,数据隐私、数据共享和算法透明性等问题仍需解决。未来,AI将在医学影像诊断中发挥更大作用,成为医生的得力助手。
786 0
|
存储 关系型数据库 MySQL
手把手教教会你使用Wing FTP Server安装配置并结合内网穿透实现公网访问本地站点
手把手教教会你使用Wing FTP Server安装配置并结合内网穿透实现公网访问本地站点
|
缓存 关系型数据库 数据库
postgresql.conf配置详解
postgresql.conf配置详解
|
SQL 关系型数据库 MySQL
MySQL中的12个SQL编写规范
SQL良好习惯提升查询清晰度、效率和安全性,包括使用EXPLAIN分析查询计划、DELETE/UPDATE时加LIMIT限制影响范围、为表和字段添加注释、关键字大写缩进、指定INSERT字段名、先测试后执行、表含主键及时间戳字段、Update/Delete需Where条件、用InnoDB引擎、避免SELECT *,选择UTF8字符集和规范索引命名。
MySQL中的12个SQL编写规范
|
Python
解决Pycharm安装后无法导入库的问题
解决Pycharm导入库问题:进入Settings,选择Project的`Python Interpreter`,点击Add Interpreter。删除`.venv`文件夹内容,然后关闭并重启Pycharm以初始化新环境,现在可以正常导入库了。
793 1
解决Pycharm安装后无法导入库的问题