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

ASP.NET Core 7 Web API如何为不同端点配置两种认证方式?

解决ASP.NET Core 7中同时配置Azure AD B2C和Basic Auth认证的问题

问题根源

你遇到的核心问题是混淆了**认证(Authentication)和授权(Authorization)**的职责:

  1. 仅实现授权处理程序(AuthorizationHandler)不足以让Basic Auth成为有效的认证方式,Azure AD B2C的认证中间件会优先检查请求,没有AD令牌直接返回401。
  2. 添加[AllowAnonymous]会跳过所有认证和授权校验,导致两种规则都失效。

解决方案

要为不同端点配置独立的认证方式,需要分别注册两种认证方案,并通过授权策略绑定到对应端点。


步骤1:实现Basic Auth认证处理程序

替换原有的授权处理程序,实现AuthenticationHandler来处理Basic Auth的身份验证:

public class BasicAuthOptions : AuthenticationSchemeOptions
{
    public string Username { get; set; }
    public string Password { get; set; }
}

public class BasicAuthHandler : AuthenticationHandler<BasicAuthOptions>
{
    public BasicAuthHandler(IOptionsMonitor<BasicAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
        : base(options, logger, encoder, clock)
    {
    }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        if (!Request.Headers.ContainsKey("Authorization"))
            return Task.FromResult(AuthenticateResult.NoResult());

        try
        {
            var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
            var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
            var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':', 2);
            
            var username = credentials[0];
            var password = credentials[1];

            if (username.Equals(Options.Username, StringComparison.OrdinalIgnoreCase) && password.Equals(Options.Password))
            {
                var claims = new[] { new Claim(ClaimTypes.Name, username) };
                var identity = new ClaimsIdentity(claims, Scheme.Name);
                var principal = new ClaimsPrincipal(identity);
                var ticket = new AuthenticationTicket(principal, Scheme.Name);

                return Task.FromResult(AuthenticateResult.Success(ticket));
            }

            return Task.FromResult(AuthenticateResult.Fail("Invalid username or password"));
        }
        catch
        {
            return Task.FromResult(AuthenticateResult.Fail("Invalid authorization header format"));
        }
    }
}

步骤2:注册认证方案与授权策略

在Program.cs中同时注册Azure AD B2C和Basic Auth认证,并配置对应的授权策略:

var builder = WebApplication.CreateBuilder(args);

// 添加控制器服务
builder.Services.AddControllers();

// 注册认证方案:Azure AD B2C + Basic Auth
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    // Azure AD B2C配置(保留原有正常运行的配置)
    .AddJwtBearer(options =>
    {
        options.Authority = "https://your-b2c-tenant.b2clogin.com/your-tenant-id/your-policy/v2.0";
        options.Audience = "your-client-id";
        // 其他Azure AD B2C相关配置...
    })
    // Basic Auth配置
    .AddScheme<BasicAuthOptions, BasicAuthHandler>("BasicAuth", options =>
    {
        // 从appsettings.json读取配置
        options.Username = builder.Configuration["BasicAuth:Username"];
        options.Password = builder.Configuration["BasicAuth:Password"];
    });

// 配置授权策略
builder.Services.AddAuthorization(options =>
{
    // 默认策略:使用Azure AD B2C认证
    options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser()
        .Build();

    // Basic Auth专属策略:指定使用BasicAuth认证方案
    options.AddPolicy("BasicAuth", policy =>
        policy.AddAuthenticationSchemes("BasicAuth")
              .RequireAuthenticatedUser());
});

var app = builder.Build();

// 启用认证与授权中间件(顺序不能错)
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

步骤3:为端点绑定对应策略

在控制器中,为不同端点指定对应的授权策略:

[ApiController]
[Route("api/[controller]")]
public class SampleController : ControllerBase
{
    // 使用Azure AD B2C认证(默认策略)
    [Authorize]
    [HttpGet("ad-protected")]
    public IActionResult AdProtectedEndpoint()
    {
        return Ok("已通过Azure AD B2C认证");
    }

    // 使用Basic Auth认证
    [Authorize(Policy = "BasicAuth")]
    [HttpGet("basic-protected")]
    public IActionResult BasicProtectedEndpoint()
    {
        return Ok("已通过Basic Auth认证");
    }
}

可选:支持同时使用两种认证方式

如果需要某个端点允许用户选择Azure AD B2C或Basic Auth认证,可以添加多方案支持的策略:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AllowAdOrBasic", policy =>
        policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme, "BasicAuth")
              .RequireAuthenticatedUser());
});

然后在端点上使用:

[Authorize(Policy = "AllowAdOrBasic")]
[HttpGet("multi-auth")]
public IActionResult MultiAuthEndpoint()
{
    return Ok("已通过Azure AD B2C或Basic Auth认证");
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 22:24:55