ASP.NET Core Windows认证下,如何为当前用户从AD获取额外声明?
解决ASP.NET Core Windows认证中获取Active Directory额外声明的问题
Windows认证默认仅会加载用户的基础身份声明(如SID、用户名),要获取Email、NameIdentifier这类额外的AD属性,你可以通过自定义Claims转换的方式实现,具体步骤如下:
1. 安装必要的NuGet包
如果需要通过AD管理API查询用户属性,安装System.DirectoryServices.AccountManagement包:
Install-Package System.DirectoryServices.AccountManagement
2. 实现自定义Claims转换器
创建一个类实现IClaimsTransformation接口,在转换方法中从AD拉取所需属性并添加到用户声明集合:
using System.Security.Claims; using System.DirectoryServices.AccountManagement; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Logging; public class AdClaimsTransformer : IClaimsTransformation { private readonly ILogger<AdClaimsTransformer> _logger; public AdClaimsTransformer(ILogger<AdClaimsTransformer> logger) { _logger = logger; } public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal) { // 仅处理Windows认证的用户身份 if (principal.Identity is not WindowsIdentity windowsIdentity) { return principal; } var claimsIdentity = (ClaimsIdentity)principal.Identity; try { // 连接到当前域的AD上下文 using var principalContext = new PrincipalContext(ContextType.Domain); using var userPrincipal = UserPrincipal.FindByIdentity(principalContext, windowsIdentity.Name); if (userPrincipal == null) { return principal; } // 添加Email声明 if (!string.IsNullOrWhiteSpace(userPrincipal.EmailAddress)) { claimsIdentity.AddClaim(new Claim(ClaimTypes.Email, userPrincipal.EmailAddress)); } // 添加NameIdentifier声明(用用户SID作为唯一标识,也可改用AD对象GUID) var sidClaim = claimsIdentity.FindFirst(ClaimTypes.Sid); if (sidClaim != null) { claimsIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, sidClaim.Value)); } // 可选:添加其他需要的AD属性,比如显示名、部门 if (!string.IsNullOrWhiteSpace(userPrincipal.DisplayName)) { claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, userPrincipal.DisplayName)); } } catch (Exception ex) { _logger.LogError(ex, "Failed to retrieve AD claims for user {UserName}", windowsIdentity.Name); } return principal; } }
3. 注册Claims转换服务
在Program.cs中注册自定义的Claims转换器:
var builder = WebApplication.CreateBuilder(args); // 注册Windows认证 builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme) .AddNegotiate(); // 注册自定义Claims转换器 builder.Services.AddScoped<IClaimsTransformation, AdClaimsTransformer>(); // 其他服务配置... var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); // 中间件路由配置... app.Run();
注意事项
- 确保应用池的运行身份具备读取Active Directory用户属性的权限,否则会出现AD查询失败的情况。
- 如果你的应用部署在非域环境,需要调整
PrincipalContext的参数,指定域服务器地址和凭据。 - NameIdentifier声明没有固定的AD对应属性,这里用SID作为唯一标识是通用方案,你也可以根据需求改用用户的
ObjectGUID(需转换为字符串格式)。
内容的提问来源于stack exchange,提问作者DanB
相关产品推荐
相关产品推荐

