详解.NET 6 Web API中通过Token获取当前登录用户信息

南乔
南乔
发布时间:2026-10-16 | 6人浏览过
原创

在前序的.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获取当前登录用户信息的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表