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

如何让ASP.NET Core接口支持API密钥或Bearer令牌双认证?

解决方案:让ASP.NET Core 8 Web API接口支持Bearer令牌或API密钥任意一种认证

核心思路

问题出在你同时使用多个独立的[Authorize]属性时,ASP.NET Core默认只会尝试第一个认证方案,导致Bearer令牌的声明无法被正确识别。正确的做法是创建一个包含两种认证方案的自定义授权策略,让框架自动尝试两种认证方式,只要其中一种通过即可进入权限校验环节。

步骤1:确保两种认证方案注册时指定明确名称

在Program.cs中注册认证服务时,给API密钥认证指定唯一方案名(比如"ApiKey"),Bearer令牌使用默认的JwtBearerDefaults.AuthenticationScheme即可:

// 注册Bearer令牌认证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        // 你的Bearer配置(密钥、 issuer、audience等)
    });

// 注册API密钥认证(假设你已经实现了ApiKeyAuthenticationHandler)
builder.Services.AddAuthentication()
    .AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>("ApiKey", options =>
    {
        // 你的API密钥配置(比如密钥存储位置、验证逻辑等)
    });

步骤2:创建支持双认证的自定义授权策略

在Program.cs中添加授权策略,同时包含两种认证方案,并添加必要的权限校验要求:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AllowBearerOrApiKey", policy =>
    {
        // 添加两种认证方案,框架会依次尝试,只要一种通过认证即可
        policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
        policy.AuthenticationSchemes.Add("ApiKey");
        
        // 要求用户必须通过认证(两种方式任意一种)
        policy.RequireAuthenticatedUser();
        
        // 如果需要自定义权限校验,添加你的授权要求(比如之前的AuthorizationHandler对应的Requirement)
        policy.Requirements.Add(new YourCustomPermissionRequirement());
    });
});

步骤3:调整API密钥认证的ClaimsPrincipal生成

确保你的ApiKeyAuthenticationHandler在验证通过后,生成包含必要声明的ClaimsPrincipal,这样授权逻辑可以统一处理两种认证用户:

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
    // 你的API密钥验证逻辑(从Header/Query获取密钥、校验有效性)
    if (!TryGetApiKey(out var apiKey) || !await ValidateApiKey(apiKey))
    {
        return AuthenticateResult.Fail("Invalid API Key");
    }

    // 生成API密钥用户的声明(比如添加角色、用户ID等)
    var claims = new[]
    {
        new Claim(ClaimTypes.NameIdentifier, apiKeyOwnerId),
        new Claim(ClaimTypes.Role, "ApiClient") // 标记为API密钥用户,方便授权校验
    };
    
    var identity = new ClaimsIdentity(claims, Scheme.Name);
    var principal = new ClaimsPrincipal(identity);
    
    return AuthenticateResult.Success(new AuthenticationTicket(principal, Scheme.Name));
}

步骤4:调整AuthorizationHandler支持双认证用户

修改你的自定义AuthorizationHandler,使其能同时处理Bearer令牌用户和API密钥用户的权限校验:

public class YourCustomPermissionHandler : AuthorizationHandler<YourCustomPermissionRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, YourCustomPermissionRequirement requirement)
    {
        var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
        if (string.IsNullOrEmpty(userId))
        {
            context.Fail();
            return Task.CompletedTask;
        }

        // 从HttpContext获取路由参数(比如客户ID)
        if (context.Resource is HttpContext httpContext)
        {
            var customerId = httpContext.Request.RouteValues["id"]?.ToString();
            
            // 权限校验逻辑:
            // 1. Bearer用户:校验用户是否有权访问该客户数据
            // 2. API密钥用户:直接通过(或根据你的业务逻辑校验)
            if (IsBearerUserAuthorized(userId, customerId) || context.User.IsInRole("ApiClient"))
            {
                context.Succeed(requirement);
                return Task.CompletedTask;
            }
        }

        context.Fail();
        return Task.CompletedTask;
    }

    // 实现Bearer用户的权限校验逻辑
    private bool IsBearerUserAuthorized(string userId, string customerId)
    {
        // 你的业务逻辑:比如用户ID与客户ID关联校验
        return userId == customerId;
    }
}

步骤5:在接口上应用自定义策略

将接口上的多个[Authorize]属性替换为自定义策略:

[ApiController]
[Route("api/customer")]
public class CustomerController : ControllerBase
{
    [HttpGet("{id}")]
    [Authorize(Policy = "AllowBearerOrApiKey")]
    public IActionResult GetCustomer(string id)
    {
        // 你的接口逻辑
        return Ok(new { CustomerId = id });
    }
}

关键注意事项

  1. 确保中间件顺序正确:app.UseAuthentication()必须在app.UseAuthorization()之前
  2. 测试两种认证方式:分别用有效Bearer令牌、有效API密钥访问接口,确认都能正常返回数据;无认证信息时返回403
  3. 避免重复端点:通过策略复用同一个接口,无需创建冗余路由

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 09:53:11