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

如何从ASP.NET Core多认证方案中获取所有Claim?

多阶段身份验证问题:无法合并多个认证Scheme的Claim

我们需要实现多阶段身份验证流程:先以普通用户身份通过scheme1(Cookie有效期较长)完成登录,再额外以超级用户身份通过scheme2(Cookie有效期较短)登录。但目前遇到问题:调用/info接口时,仅能获取到scheme1中的Claim,无法同时获取两个认证方案的Claim。

问题复现代码

using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;

const string scheme1 = "cookie1";
const string scheme2 = "cookie2";

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(scheme1)
                .AddCookie(scheme1)
                .AddCookie(scheme2);

var app = builder.Build();
app.UseAuthentication();

app.MapGet("/info", (HttpContext ctx) => string.Join(", ", ctx.User.Claims.Select(c => $"[{c}]")));

app.MapGet("/login", async (HttpContext ctx) =>
{
    await ctx.SignInAsync(scheme1, new(new ClaimsIdentity([new("key1", "val1")], "id1")));
    await ctx.SignInAsync(scheme2, new(new ClaimsIdentity([new("key2", "val2")], "id2")));
    return "multistage login simulation";
});

app.Run();

问题原因

ASP.NET Core默认只会自动验证配置的默认认证Scheme(此处为scheme1),不会主动触发其他Scheme的身份验证流程,因此ctx.User仅包含默认Scheme解析出的Claim。

解决方案

方案1:接口内手动验证并合并Claim

修改/info接口逻辑,手动验证scheme2并合并两个Scheme的Claim:

app.MapGet("/info", async (HttpContext ctx) =>
{
    // 获取默认scheme1的身份信息
    var identity1 = ctx.User.Identities.FirstOrDefault();
    
    // 手动验证scheme2
    var result2 = await ctx.AuthenticateAsync(scheme2);
    var identity2 = result2.Principal?.Identities.FirstOrDefault();

    // 合并两个身份的Claim
    var allClaims = new List<Claim>();
    if (identity1 != null) allClaims.AddRange(identity1.Claims);
    if (identity2 != null) allClaims.AddRange(identity2.Claims);

    return string.Join(", ", allClaims.Select(c => $"[{c}]"));
});

方案2:全局中间件处理多Scheme验证

如果多个接口都需要合并多Scheme的Claim,可添加自定义中间件统一处理:

var app = builder.Build();

// 自定义中间件:验证多个Scheme并合并身份
app.Use(async (context, next) =>
{
    // 执行默认scheme1的认证
    await context.AuthenticateAsync(scheme1);
    
    // 手动验证scheme2
    var scheme2Result = await context.AuthenticateAsync(scheme2);
    if (scheme2Result.Succeeded && scheme2Result.Principal != null)
    {
        // 将scheme2的身份合并到当前User中
        context.User.AddIdentity(scheme2Result.Principal.Identities.First());
    }

    await next();
});

app.MapGet("/info", (HttpContext ctx) => string.Join(", ", ctx.User.Claims.Select(c => $"[{c}]")));

// 登录接口保持不变
app.MapGet("/login", async (HttpContext ctx) =>
{
    await ctx.SignInAsync(scheme1, new(new ClaimsIdentity([new("key1", "val1")], "id1")));
    await ctx.SignInAsync(scheme2, new(new ClaimsIdentity([new("key2", "val2")], "id2")));
    return "multistage login simulation";
});

app.Run();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:42:44