如何为AbpSession添加Username并替代UserId使用?
扩展AbpSession添加Username字段的实现方案
嘿,这个需求很实用,我来一步步带你完成AbpSession的扩展,让它支持Username字段:
1. 定义自定义Session接口
首先,我们需要创建一个继承自IAbpSession的新接口,添加Username属性:
public interface ICustomAbpSession : IAbpSession { // 新增Username属性 string Username { get; } }
2. 实现自定义Session类
接下来实现这个接口,继承AbpSessionBase,从用户的Claims中获取Username(ABP默认将用户身份信息存储在Claims里):
public class CustomAbpSession : AbpSessionBase, ICustomAbpSession { // 从Claims中提取Username public string Username => GetClaimValue(ClaimTypes.Name); public CustomAbpSession(IPrincipalAccessor principalAccessor, IMultiTenancyConfig multiTenancyConfig) : base(principalAccessor, multiTenancyConfig) { } // 通用的Claim获取方法 private string GetClaimValue(string claimType) { var claim = PrincipalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == claimType); return claim?.Value; } }
注:如果你的系统中Username对应的Claim类型不是ClaimTypes.Name,可以替换成自定义的ClaimKey,比如"custom_username"
3. 替换默认的AbpSession服务
在你的模块类的PreInitialize方法中,用自定义的Session替换框架默认的实现:
public override void PreInitialize() { // 注册自定义Session接口 IocManager.Register<ICustomAbpSession, CustomAbpSession>(DependencyLifeStyle.Transient); // 可选:替换默认的IAbpSession,这样原有注入IAbpSession的地方也能拿到Username IocManager.Replace<IAbpSession, CustomAbpSession>(DependencyLifeStyle.Transient); }
4. 确保登录时添加Username到Claims
要让Session能拿到Username,必须在用户登录时把Username写入Claims。比如在登录逻辑中生成ClaimsPrincipal时添加:
public async Task<AuthenticateResult> LoginAsync(string username, string password) { // 验证用户逻辑... var user = await _userManager.FindByNameAsync(username); // 构建Claims列表 var claims = new List<Claim> { new Claim(ClaimTypes.Name, user.UserName), // 添加Username Claim new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), // 其他必要的Claims(如角色、租户等)... }; var identity = new ClaimsIdentity(claims, "Bearer"); var principal = new ClaimsPrincipal(identity); // 后续登录流程... }
5. 使用自定义Session获取Username
现在就可以在服务或控制器中注入ICustomAbpSession(或者IAbpSession,如果你替换了默认实现)来获取Username了:
public class OrderService : ITransientDependency { private readonly ICustomAbpSession _abpSession; public OrderService(ICustomAbpSession abpSession) { _abpSession = abpSession; } public void CreateOrder() { var currentUsername = _abpSession.Username; // 使用currentUsername进行业务处理,比如记录操作人 Console.WriteLine($"订单由用户 {currentUsername} 创建"); } }
额外说明(针对ABP vNext)
如果是ABP vNext版本,扩展思路完全一致,只是接口和基类名称略有不同:
- 接口继承
IAbpSession - 实现类继承
AbpSession - 替换服务的方式改为在模块的
ConfigureServices方法中使用services.Replace:
public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.Replace(ServiceDescriptor.Transient<IAbpSession, CustomAbpSession>()); }
这样就完成了AbpSession的扩展,以后就能直接从Session中获取更直观的Username字段啦~
内容的提问来源于stack exchange,提问作者Hoang Tran
相关产品推荐
相关产品推荐

