详解.NET 6 Web API中通过Token获取当前登录用户信息
在前序的.NET 6 TodoList开发文章中,我们在领域实体保存时硬编码了`Anonymous`作为创建和修改者,导致数据缺乏可追溯性。本文的目标是实现自动获取当前登录用户的信息,并将其正确写入数据库。
目标与原理
核心目标是:实现在保存数据时填入当前登陆的操作用户名。
原理上,当用户通过认证后,返回的JWT(JSON Web Token)的payload部分包含了用户的Claim信息(如UserName)。我们需要利用.NET提供的IHttpContextAccessor对象,从当前请求上下文中提取这些Claim,进而获取到用户名,并在数据库层面对其进行持久化。
准备条件
1. 已完成的.NET 6 Web API基础架构。
2. 已实现的JWT认证逻辑,确保Token中包含ClaimTypes.Name(即UserName)。
3. 用于测试的TodoList应用及相关的领域实体模型。
真实操作顺序
第1步:定义当前用户服务接口
目的:定义抽象契约,解耦具体实现,便于后续测试和维护。
入口:Application/Common/Interfaces目录
动作:新建 ICurrentUserService.cs,声明一个只读属性用于暴露用户名:
namespace TodoList.Application.Common.Interfaces;
public interface ICurrentUserService
{
string? UserName { get; }
}
参数说明:若需获取UserId或其他信息,需在JWT签发时的Claims生成代码中添加相应字段。例如演示代码中添加了Role和Name:
// 演示了返回用户名和Role两个claims
var claims = new List<Claim>
{
// Claims中包含UserName信息
new(ClaimTypes.Name, User!.UserName),
new(JwtRegisteredClaimNames.Iss, _jwtConfiguration.ValidIssuer ?? "TodoListApi"),
new(JwtRegisteredClaimNames.Aud, _jwtConfiguration.ValidAudience ?? "http://localhost:5050")
};
第2步:实现用户服务接口
目的:通过HTTP上下文获取当前认证用户的实际名称。
入口:Api/Services目录
动作:新建 CurrentUserService.cs,注入IHttpContextAccessor并读取Claims:
using System.Security.Claims;
using TodoList.Application.Common.Interfaces;
namespace TodoList.Api.Services;
public class CurrentUserService : ICurrentUserService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public CurrentUserService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
// 通过注入的IHttpContextAccessor获取`HttpContext.User(ClaimsPrinciple)`中对应的Claims信息
public string? UserName => _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.Name);
}
重要配置:必须在 Program.cs 中将此服务注册为单例(Singleton),以确保整个生命周期内共享同一个访问器实例:
builder.Services.AddSingleton<ICurrentUserService, CurrentUserService>();
第3步:在DbContext中使用该服务
目的:在每次保存更改前,自动填充审计字段。
入口:TodoListDbContext.cs
动作A:构造函数注入。将ICurrentUserService加入构造函数参数:
private readonly ICurrentUserService _currentUserService;
public TodoListDbContext(
DbContextOptions<TodoListDbContext> options,
IDomainEventService domainEventService,
ICurrentUserService currentUserService) : base(options)
{
_domainEventService = domainEventService;
_currentUserService = currentUserService;
}
动作B:重写SaveChangesAsync。遍历变更追踪中的AuditableEntity,根据状态设置用户和时间:
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
{
foreach (var entry in ChangeTracker.Entries<AuditableEntity>())
{
switch (entry.State)
{
case EntityState.Added:
entry.Entity.CreatedBy = _currentUserService.UserName;
entry.Entity.Created = DateTime.UtcNow;
break;
case EntityState.Modified:
entry.Entity.LastModifiedBy = _currentUserService.UserName;
entry.Entity.LastModified = DateTime.UtcNow;
break;
}
}
// 省略其他...
return await base.SaveChangesAsync(cancellationToken);
}
验证
启动 Api 项目,首先通过认证接口获取合法的 Token。接着使用该 Token 发起请求,创建一个新的 TodoList 任务。
从请求响应或日志中可以看到,新创建的记录已携带当前用户信息。为确保数据确实落盘,我们直接查询数据库进行最终确认:
数据库结果显示,CreatedBy 和 LastModifiedBy 字段已成功填充为当前登录用户名,而非之前的占位符。
总结
本文详细介绍了在.NET 6应用中,如何结合JWT认证机制与EF Core的拦截器功能,自动处理数据审计信息的录入。通过IHttpContextAccessor解析Token中的Claim,再配合依赖注入在DbContext层面统一处理,既保证了业务逻辑的纯净,又实现了关键数据的自动化记录。以上就是.NET 6实现获取当前登录用户信息并自动落盘的详细内容,更多关于.NET 6获取当前登录用户信息的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













