在ASP.NET Core的身份认证体系中,ClaimsPrincipal是表示用户身份的核心对象,它包含了用户的所有声明信息,我们可以通过它获取当前登录用户的各类身份数据,比如用户ID、用户名、角色等。

ClaimsPrincipal基础概念
ClaimsPrincipal对象内部包含一个或多个ClaimsIdentity,每个ClaimsIdentity又由多个Claim组成。Claim是最小的身份单元,每个Claim都有一个类型(ClaimType)和对应的值(Value),常见的Claim类型有用户ID、用户名、邮箱、角色等。
我们可以通过ClaimsPrincipal的FindFirst方法查找指定类型的声明,也可以通过Claims属性遍历所有声明信息。
控制器中获取当前用户信息
在ASP.NET Core的控制器中,当前用户的ClaimsPrincipal对象可以直接通过User属性获取,这是最常用的获取场景。
获取基础用户信息示例
以下代码演示了在控制器中获取用户ID和用户名的操作:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
[Authorize]
[ApiController]
[Route("api/user")]
public class UserController : ControllerBase
{
[HttpGet("info")]
public IActionResult GetUserInfo()
{
// 获取当前用户的ClaimsPrincipal对象
ClaimsPrincipal principal = User;
// 获取用户ID,假设用户ID的声明类型为ClaimTypes.NameIdentifier
string userId = principal.FindFirstValue(ClaimTypes.NameIdentifier);
// 获取用户名,假设用户名的声明类型为ClaimTypes.Name
string userName = principal.FindFirstValue(ClaimTypes.Name);
// 获取用户邮箱
string email = principal.FindFirstValue(ClaimTypes.Email);
// 获取用户所有角色
List<string> roles = principal.FindAll(ClaimTypes.Role).Select(c => c.Value).ToList();
return Ok(new
{
UserId = userId,
UserName = userName,
Email = email,
Roles = roles
});
}
}
自定义扩展方法简化获取
如果频繁需要获取用户ID等信息,可以编写扩展方法简化操作:
using System.Security.Claims;
public static class ClaimsPrincipalExtensions
{
// 扩展方法获取用户ID
public static string GetUserId(this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return principal.FindFirstValue(ClaimTypes.NameIdentifier);
}
// 扩展方法获取用户名
public static string GetUserName(this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return principal.FindFirstValue(ClaimTypes.Name);
}
}
使用扩展方法后,控制器中的代码可以简化为:
[HttpGet("simple-info")]
public IActionResult GetSimpleUserInfo()
{
string userId = User.GetUserId();
string userName = User.GetUserName();
return Ok(new { UserId = userId, UserName = userName });
}
非控制器场景中获取用户信息
除了控制器,我们还可能在中间件、后台服务、自定义类中需要获取当前用户信息,这时候需要通过注入IHttpContextAccessor来获取HttpContext,进而拿到User对象。
中间件中获取用户信息
首先在Program.cs中注册IHttpContextAccessor:
var builder = WebApplication.CreateBuilder(args); // 注册IHttpContextAccessor builder.Services.AddHttpContextAccessor(); // 添加身份认证服务(示例,实际根据项目配置) builder.Services.AddAuthentication(); var app = builder.Build(); // 使用认证中间件 app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
然后在中间件中获取用户信息:
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System.Threading.Tasks;
public class UserMiddleware
{
private readonly RequestDelegate _next;
private readonly IHttpContextAccessor _httpContextAccessor;
public UserMiddleware(RequestDelegate next, IHttpContextAccessor httpContextAccessor)
{
_next = next;
_httpContextAccessor = httpContextAccessor;
}
public async Task InvokeAsync(HttpContext context)
{
// 获取当前HttpContext
HttpContext currentContext = _httpContextAccessor.HttpContext;
if (currentContext != null && currentContext.User.Identity.IsAuthenticated)
{
ClaimsPrincipal principal = currentContext.User;
string userId = principal.FindFirstValue(ClaimTypes.NameIdentifier);
// 这里可以添加自定义逻辑,比如记录用户操作日志
}
await _next(context);
}
}
后台服务中获取用户信息
后台服务如果需要获取用户信息,同样需要依赖IHttpContextAccessor,但要注意后台服务可能没有活跃的HttpContext,因此需要在有请求上下文的场景下使用:
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
public class UserBackgroundService : BackgroundService
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ILogger<UserBackgroundService> _logger;
public UserBackgroundService(IHttpContextAccessor httpContextAccessor, ILogger<UserBackgroundService> logger)
{
_httpContextAccessor = httpContextAccessor;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
// 注意:后台服务默认没有HttpContext,这里的示例仅适用于有上下文注入的场景
HttpContext context = _httpContextAccessor.HttpContext;
if (context != null && context.User.Identity.IsAuthenticated)
{
ClaimsPrincipal principal = context.User;
string userName = principal.FindFirstValue(ClaimTypes.Name);
_logger.LogInformation("当前登录用户:{UserName}", userName);
}
await Task.Delay(1000, stoppingToken);
}
}
}
自定义声明添加与读取
实际开发中我们经常需要添加自定义的声明,比如用户的部门、手机号等,然后在使用时读取这些自定义声明。
登录时添加自定义声明
在用户登录生成身份票据时,可以添加自定义声明:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Security.Claims;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
[HttpPost("login")]
public async Task<IActionResult> Login(string userName, string password)
{
// 这里假设验证用户名密码通过
List<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, "1001"),
new Claim(ClaimTypes.Name, userName),
// 自定义声明:用户部门
new Claim("Department", "技术部"),
// 自定义声明:用户手机号
new Claim("PhoneNumber", "13800138000")
};
ClaimsIdentity identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal principal = new ClaimsPrincipal(identity);
// 登录,生成认证Cookie
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
return Ok("登录成功");
}
读取自定义声明
读取自定义声明的方式和读取系统声明一致,只需要指定对应的声明类型即可:
[HttpGet("custom-claims")]
public IActionResult GetCustomClaims()
{
ClaimsPrincipal principal = User;
// 读取自定义部门声明
string department = principal.FindFirstValue("Department");
// 读取自定义手机号声明
string phoneNumber = principal.FindFirstValue("PhoneNumber");
return Ok(new
{
Department = department,
PhoneNumber = phoneNumber
});
}
注意事项
- 获取用户信息前要确保用户已经通过身份认证,否则User对象可能为空或者没有对应的声明,建议配合
[Authorize]特性使用,或者在获取前判断User.Identity.IsAuthenticated的值。 - 声明类型尽量使用系统预定义的
ClaimTypes中的常量,比如ClaimTypes.NameIdentifier、ClaimTypes.Name,避免自定义字符串出现拼写错误。 - 如果项目使用了JWT认证,声明的类型可能和Cookie认证有差异,需要根据实际的token载荷中的字段来调整查找的声明类型。
- 在非请求上下文的场景下,比如完全没有Http请求的后台任务,无法通过
IHttpContextAccessor获取用户信息,需要重新设计信息传递方式。
C#ClaimsPrincipalASP.NET_Core用户信息获取修改时间:2026-07-17 08:57:45