.NET Core WebAPI中基于X-API-Key绕过OAuth认证的方案问询
.NET Core WebAPI 实现API Key绕过OAuth认证方案
实现步骤
1. 创建API Key认证处理逻辑
首先定义自定义的API Key认证方案和处理类,负责验证请求头中的X-API-Key:
using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Options; using System.Security.Claims; using System.Text.Encodings.Web; // API Key认证配置项 public class ApiKeyAuthOptions : AuthenticationSchemeOptions { public const string SchemeName = "API-Key"; public string HeaderName { get; set; } = "X-API-Key"; } // API Key认证处理类 public class ApiKeyAuthHandler : AuthenticationHandler<ApiKeyAuthOptions> { private readonly IApiKeyValidator _validator; public ApiKeyAuthHandler( IOptionsMonitor<ApiKeyAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IApiKeyValidator validator) : base(options, logger, encoder, clock) { _validator = validator; } protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { // 检查请求头是否包含API Key if (!Request.Headers.TryGetValue(Options.HeaderName, out var headerValues)) { // 无API Key,返回无结果,交由后续认证方案处理 return AuthenticateResult.NoResult(); } var apiKey = headerValues.FirstOrDefault(); if (string.IsNullOrWhiteSpace(apiKey)) { return AuthenticateResult.Fail("API Key不能为空"); } // 验证API Key有效性(替换为你的实际验证逻辑) var user = await _validator.ValidateAsync(apiKey); if (user == null) { return AuthenticateResult.Fail("无效的API Key"); } // 生成认证票据 var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), new Claim(ClaimTypes.Name, user.Username) // 可添加其他用户权限Claim }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); return AuthenticateResult.Success(ticket); } } // API Key验证服务接口(需自行实现具体逻辑) public interface IApiKeyValidator { Task<User> ValidateAsync(string apiKey); } // 示例验证实现(实际应从数据库/配置中心读取有效API Key) public class ApiKeyValidator : IApiKeyValidator { public async Task<User> ValidateAsync(string apiKey) { // 示例:仅验证固定API Key,实际需替换为持久化存储验证 if (apiKey.Equals("your-valid-api-key-xxx", StringComparison.OrdinalIgnoreCase)) { return await Task.FromResult(new User { Id = 1, Username = "Api_User" }); } return null; } } // 用户模型(根据你的业务调整) public class User { public int Id { get; set; } public string Username { get; set; } }
2. 配置Program.cs中的认证与授权
在现有OAuth/Cookie认证配置基础上,添加API Key认证方案,并调整授权策略支持多认证方式:
var builder = WebApplication.CreateBuilder(args); // 注册API Key验证服务 builder.Services.AddScoped<IApiKeyValidator, ApiKeyValidator>(); // 配置认证服务 builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) // 原有Cookie认证配置 .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.Cookie.Name = "Your_Auth_Cookie"; options.LoginPath = "/auth/login"; // 其他Cookie配置... }) // 原有OAuth认证配置 .AddOAuth("Your_OAuth_Scheme", options => { options.ClientId = builder.Configuration["OAuth:ClientId"]; options.ClientSecret = builder.Configuration["OAuth:ClientSecret"]; options.CallbackPath = "/auth/signin-oauth"; // 原有OAuth事件处理 options.Events = new OAuthEvents { OnCreatingTicket = context => { OAuthHelper.Process(context); return Task.CompletedTask; } }; }) // 添加API Key认证方案 .AddScheme<ApiKeyAuthOptions, ApiKeyAuthHandler>( ApiKeyAuthOptions.SchemeName, options => { }); // 配置授权策略,允许API Key、Cookie、OAuth三种认证方式 builder.Services.AddAuthorization(options => { options.FallbackPolicy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .AddAuthenticationSchemes( ApiKeyAuthOptions.SchemeName, CookieAuthenticationDefaults.AuthenticationScheme, "Your_OAuth_Scheme") .Build(); }); builder.Services.AddControllers(); var app = builder.Build(); // 中间件顺序:认证在前,授权在后 app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
关键逻辑说明
- 当请求携带
X-API-Key头时,ApiKeyAuthHandler会优先验证:- 验证通过则生成认证票据,认证成功,后续OAuth/Cookie中间件不会执行
- 验证失败或无API Key时,返回
NoResult,系统自动尝试后续的OAuth/Cookie认证流程
- 授权策略中包含所有允许的认证方案,确保两种认证方式都能通过授权校验
- 需根据业务实际实现
IApiKeyValidator的验证逻辑,比如从数据库查询有效API Key关联的用户信息
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

