You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为Azure Active Directory Web应用登录添加自定义声明

在Azure AD登录的.NET Core 6 Razor Pages中添加自定义声明

方法一:使用ClaimsTransformation(通用方案)

这是.NET认证体系的标准扩展方式,可在用户身份验证流程中(含每次请求或登录时)注入自定义声明。

  1. 创建实现IClaimsTransformation的自定义转换类:
public class CustomClaimsTransformer : IClaimsTransformation
{
    private readonly IUserRepository _userRepository;
    private readonly ILoginClaimRepository _loginClaimRepository;

    public CustomClaimsTransformer(IUserRepository userRepository, ILoginClaimRepository loginClaimRepository)
    {
        _userRepository = userRepository;
        _loginClaimRepository = loginClaimRepository;
    }

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        // 克隆身份对象,避免修改原始实例
        var clonedPrincipal = principal.Clone();
        var identity = clonedPrincipal.Identity as ClaimsIdentity;

        // 从Azure AD返回的声明中获取用户唯一标识(优先用邮箱, fallback到ObjectId)
        var userId = identity?.FindFirstValue(ClaimTypes.Email) 
                     ?? identity?.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");

        if (string.IsNullOrEmpty(userId))
            return clonedPrincipal;

        // 从SQL数据库查询自定义声明列表
        var customClaims = _loginClaimRepository.ClaimList(userId);
        foreach (var claim in customClaims)
        {
            // 避免重复添加相同声明
            if (!identity.HasClaim(c => c.Type == claim.Type && c.Value == claim.Value))
            {
                identity.AddClaim(claim);
            }
        }

        return clonedPrincipal;
    }
}
  1. 在Program.cs中注册该服务:
builder.Services.AddScoped<IClaimsTransformation, CustomClaimsTransformer>();

方法二:拦截OpenID Connect登录事件(Azure AD专属)

针对Azure AD的OpenID Connect流程,可在令牌验证通过后、生成ClaimsPrincipal前的节点注入声明,仅在用户登录时触发一次。

在Program.cs的Azure AD认证配置中添加事件拦截:

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();

// 配置OpenID Connect事件
builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    options.Events = new OpenIdConnectEvents
    {
        OnTokenValidated = async context =>
        {
            // 从DI容器获取数据库仓储实例
            var userRepository = context.HttpContext.RequestServices.GetRequiredService<IUserRepository>();
            var loginClaimRepository = context.HttpContext.RequestServices.GetRequiredService<ILoginClaimRepository>();

            // 获取Azure AD用户标识
            var userId = context.Principal.FindFirstValue(ClaimTypes.Email) 
                         ?? context.Principal.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");

            if (!string.IsNullOrEmpty(userId))
            {
                var customClaims = loginClaimRepository.ClaimList(userId);
                var identity = context.Principal.Identity as ClaimsIdentity;

                foreach (var claim in customClaims)
                {
                    if (!identity.HasClaim(c => c.Type == claim.Type && c.Value == claim.Value))
                    {
                        identity.AddClaim(claim);
                    }
                }
            }

            await Task.CompletedTask;
        }
    };
});

方案对比

  • ClaimsTransformation:每次身份验证时触发(如每次请求需验证身份),适合需动态更新声明的场景。
  • OnTokenValidated:仅在用户登录获取新令牌时触发,声明会存入Cookie直到过期,适合声明不频繁变动的场景。

注意事项

  • 确保Azure AD返回的用户标识(邮箱/ObjectId)与SQL数据库中的用户记录能对应,作为查询自定义声明的依据。
  • 添加声明前需检查是否已存在,避免重复注入。
  • 若使用ClaimsTransformation,频繁查询数据库可考虑加入缓存逻辑优化性能。

内容的提问来源于stack exchange,提问作者Ed Sansbury

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 08:22:50