在IdentityServer4生成的JWT中添加一个自定义的Claim,用于ABP框架中要用到的token信息

news/2024/9/24 18:01:36

用过IdentityServer4或者熟悉ASP.NET Core认证的都应该知道有Claim,如何理解ids4中的Claim?

这里可以理解为声明,我们每个用户都有多个Claim,每个Claim声明了用户的某个信息比如:Role=Admin,UserID=1000等等,这里Role,UserID每个都是用户的Claim,都是表示用户信息的单元 ,我们不妨把它称为用户信息单元 。

Claim相关的解析 http://www.cnblogs.com/savorboard/p/aspnetcore-identity.html

需求:在ids4中加一个登录用户所属的公司ID(companyid),默认生成的token信息中的用户信息单元,一般包含如下信息:用户名、邮箱地址、电话号、角色信息等基本的用户单元信息

public virtual async Task CreateStandardResourcesAsync()
{var resources = new[]{new IdentityServer4.Models.IdentityResources.OpenId(),new IdentityServer4.Models.IdentityResources.Profile(),new IdentityServer4.Models.IdentityResources.Email(),new IdentityServer4.Models.IdentityResources.Address(),new IdentityServer4.Models.IdentityResources.Phone(),new IdentityServer4.Models.IdentityResource("role", "Roles of the user", new[] {"role"})};foreach (var resource in resources){foreach (var claimType in resource.UserClaims){await AddClaimTypeIfNotExistsAsync(claimType);}await AddIdentityResourceIfNotExistsAsync(resource);}
}

解析生成的token

 如何在解析的token中加入一个自定义的claim?比如添加一个公司ID,有两种实现方式:

方法一

1. **创建自定义声明(Claim)**:
首先,需要在用户登录的时候,将`company`信息添加到用户的声明中。你可以在你的用户存储(例如,数据库)中存储`company`信息,并在用户登录时将其添加到用户的声明中。

2. **扩展ProfileService**:
你需要创建一个自定义的`ProfileService`,以便在生成JWT时包含自定义的声明。

 public class UserProfileService : IProfileService{protected IdentityUserManager UserManager { get; }public UserProfileService(IdentityUserManager userManager){UserManager = userManager;}public async Task GetProfileDataAsync(ProfileDataRequestContext context){var user = await UserManager.GetUserAsync(context.Subject);if (user != null){var claims = new List<Claim>{new Claim("companyid", "11111"),new Claim("name",user.Name),new Claim("user_name",user.UserName),new Claim("email",user.Email),new Claim("email_verified",user.EmailConfirmed.ToString()),new Claim("phone_number",user.PhoneNumber),new Claim("phone_number_verified",user.PhoneNumberConfirmed.ToString())};// 确保添加用户的角色Claimvar roles = await UserManager.GetRolesAsync(user);foreach (var role in roles){claims.Add(new Claim("role", role));}context.IssuedClaims.AddRange(claims);}}public async Task IsActiveAsync(IsActiveContext context){var user = await UserManager.GetUserAsync(context.Subject);context.IsActive = user != null;}}

3. **配置IdentityServer4**:

将自定义的`ProfileService`注册到IdentityServer4中。

public class Startup
{public void ConfigureServices(IServiceCollection services){// 其他服务配置...// 注册自定义的Profile服务services.AddTransient<IProfileService, UserProfileService>();// IdentityServer的其他配置...
    }
}

方法二

参照APB官网给的示例,来实现,推荐方法

参见地址:
https://docs.abp.io/en/abp/latest/Authorization#claims-principal-factory
public class SocialSecurityNumberClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency
{public async Task ContributeAsync(AbpClaimsPrincipalContributorContext context){var identity = context.ClaimsPrincipal.Identities.FirstOrDefault();var userId = identity?.FindUserId();if (userId.HasValue){var userService = context.ServiceProvider.GetRequiredService<IUserService>(); //Your custom servicevar socialSecurityNumber = await userService.GetSocialSecurityNumberAsync(userId.Value);if (socialSecurityNumber != null){identity.AddClaim(new Claim("SocialSecurityNumber", socialSecurityNumber));}}}
}Configure<AbpClaimsServiceOptions>(options=>
{options.RequestedClaims.Add("SocialSecurityNumber")
})public static class CurrentUserExtensions
{public static string GetSocialSecurityNumber(this ICurrentUser currentUser){return currentUser.FindClaimValue("SocialSecurityNumber");}
}

模拟方法如下:

using AuthServer.Host.Dappers;
using IdentityServer4.Extensions;
using IdentityServer4.Models;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Users;
using static Volo.Abp.Identity.Settings.IdentitySettingNames;namespace AuthServer.Host
{public class Config{public static IEnumerable<IdentityServer4.Models.IdentityResource> GetIdentityResourceResources(){var customProfile = new IdentityServer4.Models.IdentityResource(name: "custom.profile",displayName: "Custom profile",userClaims: new[] { "companyid" });return new List<IdentityServer4.Models.IdentityResource>{new IdentityResources.OpenId(),new IdentityResources.Profile(),customProfile};}}public class UserProfileService : IProfileService{protected IdentityUserManager UserManager { get; }public UserProfileService(IdentityUserManager userManager){UserManager = userManager;}public async Task GetProfileDataAsync(ProfileDataRequestContext context){var user = await UserManager.GetUserAsync(context.Subject);if (user != null){var claims = new List<Claim>{new Claim("companyid", "11111"),new Claim("name",user.Name),new Claim("user_name",user.UserName),new Claim("email",user.Email),new Claim("email_verified",user.EmailConfirmed.ToString()),new Claim("phone_number",user.PhoneNumber),new Claim("phone_number_verified",user.PhoneNumberConfirmed.ToString())};// 确保添加用户的角色Claimvar roles = await UserManager.GetRolesAsync(user);foreach (var role in roles){claims.Add(new Claim("role", role));}context.IssuedClaims.AddRange(claims);}}public async Task IsActiveAsync(IsActiveContext context){var user = await UserManager.GetUserAsync(context.Subject);context.IsActive = user != null;}}public class SocialSecurityNumberClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency{private readonly DapperDbContext _dbDapperContext;protected IdentityUserManager UserManager { get; }public SocialSecurityNumberClaimsPrincipalContributor(DapperDbContext dbDapperContext, IdentityUserManager userManager){_dbDapperContext = dbDapperContext;UserManager = userManager;}public async Task ContributeAsync(AbpClaimsPrincipalContributorContext context){var identity = context.ClaimsPrincipal.Identities.FirstOrDefault();var userId = identity?.FindUserId();if (userId.HasValue){var user = await UserManager.GetUserAsync(context.ClaimsPrincipal);identity.AddClaim(new Claim("username", user.Name));//登录用户名string sql = @$"SELECT OrganizationId FROM [dbo].[base_user_orgs] WHERE UserId=('{userId}') ";var org=await _dbDapperContext.QueryAsync<Guid>(sql, databaseType: DatabaseType.Default);var companyId = org.Any() ? string.Join(",",org.ToList()) : "";//会有同一个属于多个公司identity.AddClaim(new Claim("companyid", companyId));//测试用//var userService = context.ServiceProvider.GetRequiredService<IUserService>(); //Your custom service//var socialSecurityNumber = await userService.GetSocialSecurityNumberAsync(userId.Value);//if (socialSecurityNumber != null)//{//    identity.AddClaim(new Claim("SocialSecurityNumber", socialSecurityNumber));//}
            }}}public static class CurrentUserExtensions{public static string GetSocialSecurityNumber(this ICurrentUser currentUser){return currentUser.FindClaimValue("companyid");}}
}

生成的实际效果

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

使用粒子滤波(particle filter)进行视频目标跟踪

虽然有许多用于目标跟踪的算法,包括较新的基于深度学习的算法,但对于这项任务,粒子滤波仍然是一个有趣的算法。所以在这篇文章中,我们将介绍视频中的目标跟踪:预测下一帧中物体的位置。在粒子滤波以及许多其他经典跟踪算法的情况下,我们根据估计的动态进行预测,然后使用…

触想工业一体机在智慧医疗智能采血管理系统中的应用

一、行业发展前景作为医院重点科室之一,传统的检验科采血环节存在诸多痛点,特别在备管阶段,大量患者信息的核对、试管条码打印、选管、贴标等繁琐步骤均依赖人工操作,工作强度大、效率低,易出错。随着智慧医院建设的广泛推行,一种集成信息化、自动化的新型设备——自动采…

01_前端环境搭建

1.下载VsCode并安装 Download Visual Studio Code - Mac, Linux, Windows 2.下载Node.js并安装 Node.js — 下载 Node.js (nodejs.org) cmd -->输入 npm -v 和 node -v,有版本返回说明正常 3.新建一个文件夹(HCJV_01),使用VsCode打开该文件夹,打开终端,跳转到该文件夹目录…

【YOLOv8改进 - 特征融合NECK】Slim-neck:目标检测新范式,既轻量又涨点

YOLO目标检测创新改进与实战案例专栏专栏目录: YOLO有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例专栏链接: YOLO基础解析+创新改进+实战案例介绍摘要 目标检测是计算机视觉中的一项重要下游任务。对于车载边缘计算…

使用某雷加速器后,无法链接网络

本人情况:在使用某雷加速器后,再次开机连接网络(校园网),可以连接,但没有弹窗或不可使用该网络! (只有再次打开该加速器网络才可用) ①点击下放搜索栏,输入:cmd②点击“以管理员身份打开” ③输入“netsh winsock reset” ④根据要求重启电脑(如果出现异常可以再次重…

ASCII 表

ASCII 表ASCII 表 https://www.runoob.com/w3cnote/ascii.html网站:http://shibowl.topgithub:https://github.com/hanbinjxnc博客园:https://www.cnblogs.com/hool 博客:https://blog.shibowl.top淘宝店:https://boxunwl.taobao.com/ 作者:世博 2019年4月28日

记一次https通讯调试过程

情况说明:和服务端https交互时,用域名的方式会有正常的应答,用指定IP的方式则提示异常。 代码抛出异常如下:javax.net.ssl.SSLHandshakeException:Remote host closed connection during handshake at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImp…

【YOLOv8改进 - 特征融合NECK】 HS-FPN :用于处理多尺度特征融合的网络结构,降低参数

摘要 在标准的医院血液检测中,传统过程需要医生使用显微镜从患者的血液显微图像中手动分离白细胞。然后,这些分离出的白细胞通过自动白细胞分类器进行分类,以确定血液样本中不同类型白细胞的比例和数量,从而辅助疾病诊断。这种方法不仅耗时费力,而且由于图像质量和环境条件…