ASP.NET Core 6 Minimal API能否自定义授权特性适配认证中间件?
实现ASP.NET Core 6 Minimal API自定义授权扩展方法
1. 定义自定义授权元数据类
先创建两个元数据类,用来存储路由的授权配置信息:
// 标记需要特定角色授权的元数据 public class CustomAuthorizationMetadata { public string[] RequiredRoles { get; } public CustomAuthorizationMetadata(params string[] requiredRoles) { RequiredRoles = requiredRoles; } } // 标记允许匿名访问的元数据 public class AllowAnonymousMetadata { }
2. 编写路由扩展方法
给RouteHandlerBuilder(Minimal API路由的返回类型)实现扩展方法,通过WithMetadata给路由添加自定义元数据:
public static class RouteAuthorizationExtensions { // 模拟原生RequiresAuthorization,支持传入角色列表 public static RouteHandlerBuilder RequiresCustomAuthorization(this RouteHandlerBuilder builder, params string[] roles) { return builder.WithMetadata(new CustomAuthorizationMetadata(roles)); } // 模拟原生AllowAnonymous public static RouteHandlerBuilder AllowCustomAnonymous(this RouteHandlerBuilder builder) { return builder.WithMetadata(new AllowAnonymousMetadata()); } }
3. 实现自定义授权中间件
中间件从当前请求的Endpoint中提取元数据,据此执行授权判断:
public class CustomAuthorizationMiddleware { private readonly RequestDelegate _next; public CustomAuthorizationMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var endpoint = context.GetEndpoint(); if (endpoint == null) { await _next(context); return; } // 优先判断是否允许匿名:存在AllowAnonymousMetadata则跳过授权 var allowAnonymous = endpoint.Metadata.GetMetadata<AllowAnonymousMetadata>(); if (allowAnonymous != null) { await _next(context); return; } // 判断是否需要角色授权:读取CustomAuthorizationMetadata var authMetadata = endpoint.Metadata.GetMetadata<CustomAuthorizationMetadata>(); if (authMetadata != null) { var user = context.User; // 未认证直接返回401 if (!user.Identity.IsAuthenticated) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; return; } // 检查用户是否拥有所需角色 var hasRequiredRole = authMetadata.RequiredRoles.Any(role => user.IsInRole(role)); if (!hasRequiredRole) { context.Response.StatusCode = StatusCodes.Status403Forbidden; return; } } // 授权通过,继续执行后续逻辑 await _next(context); } }
4. 注册中间件并使用扩展方法
在Program.cs中按顺序注册中间件(需放在认证中间件之后、路由之前),然后在路由定义中直接调用扩展方法:
var builder = WebApplication.CreateBuilder(args); // 注册你的认证服务(如JWT、Cookie等,根据实际场景配置) builder.Services.AddAuthentication(...); var app = builder.Build(); // 先启用认证,再启用自定义授权中间件 app.UseAuthentication(); app.UseMiddleware<CustomAuthorizationMiddleware>(); app.UseEndpoints(x => { // 要求Admins角色才能访问 x.MapGet("/api/something", () => Results.Ok("Admin-only content")) .RequiresCustomAuthorization("Admins"); // 允许匿名访问 x.MapGet("/api/public", () => Results.Ok("Public content")) .AllowCustomAnonymous(); // 未配置授权规则的路由:默认不做授权检查(可根据需求调整中间件逻辑) x.MapGet("/api/default", () => Results.Ok("Default content")); }); app.Run();
核心逻辑说明
- ASP.NET Core路由的
Metadata是存储路由附加信息的容器,通过WithMetadata可以给路由绑定任意自定义元数据。 - 中间件通过
context.GetEndpoint()获取当前匹配的路由端点,再用Metadata.GetMetadata<T>()提取自定义元数据,以此判断路由的授权规则。 - 可根据业务需求扩展元数据类,比如添加权限策略、自定义规则等,让授权逻辑更灵活。
内容的提问来源于stack exchange,提问作者enriquein
相关产品推荐
相关产品推荐

