ASP.NET Core 7:如何优先执行带端点元数据的本地访问过滤中间件?
ASP.NET Core 7 实现部分API仅允许本地主机访问的可行方案
核心思路
通过在UseRouting之后添加自定义中间件,既可以获取到端点元数据(识别标记了特定特性的API),又能在管道早期拦截非本地请求,避免后续不必要的管道执行。
步骤实现
- 创建自定义特性标记需要限制的API
创建一个特性类,用来标记需要仅本地访问的控制器或Action:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class LocalOnlyAttribute : Attribute { }
- 添加自定义中间件拦截请求
在Program.cs中,将中间件放在UseRouting之后、UseAuthorization之前,确保能提前获取端点元数据并拦截请求:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); var app = builder.Build(); app.UseHttpsRedirection(); // 路由匹配后即可获取端点元数据 app.UseRouting(); // 自定义本地访问拦截中间件 app.Use(async (context, next) => { var endpoint = context.GetEndpoint(); // 检查当前端点是否标记了LocalOnly特性 if (endpoint != null && endpoint.Metadata.GetMetadata<LocalOnlyAttribute>() != null) { // 判断请求是否来自本地主机 var isLocal = context.Connection.RemoteIpAddress is { } remoteIp && (IPAddress.IsLoopback(remoteIp) || context.Connection.LocalIpAddress is { } localIp && remoteIp.Equals(localIp)); if (!isLocal) { context.Response.StatusCode = StatusCodes.Status403Forbidden; await context.Response.WriteAsync("仅允许本地主机访问"); return; // 终止管道,不执行后续逻辑 } } // 符合条件则继续执行管道 await next(); }); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.Run();
- 标记需要限制的API
在目标控制器或Action上添加[LocalOnly]特性即可启用本地访问限制:
[ApiController] [Route("api/[controller]")] public class SystemController : ControllerBase { // 仅允许本地主机访问此接口 [LocalOnly] [HttpGet("system-info")] public IActionResult GetSystemInfo() { return Ok(new { OsVersion = Environment.OSVersion, MachineName = Environment.MachineName }); } // 无限制的接口 [HttpGet("public-data")] public IActionResult GetPublicData() { return Ok("公开数据内容"); } }
补充说明
- 本地请求判断逻辑:默认通过
IPAddress.IsLoopback识别回环地址(如127.0.0.1、::1),同时考虑了本地IP与远程IP一致的场景(如容器内访问)。若部署在反向代理环境下,可根据实际情况添加对X-Forwarded-For请求头的解析逻辑。 - 管道执行顺序:该中间件位于路由匹配之后、授权之前,能在请求进入MVC控制器逻辑前就完成拦截,避免了后续管道步骤的无效执行,完全符合需求。
内容的提问来源于stack exchange,提问作者Kasbolat Kumakhov
相关产品推荐
相关产品推荐

