ASP.NET Core 6中如何全局验证路由customerkey的用户访问权限
在ASP.NET Core 6中全局验证带customerkey的路由权限
针对你的需求,不需要在每个控制器/动作中重复编写验证逻辑,ASP.NET Core提供了两种合适的全局处理方式:自定义中间件或MVC全局动作过滤器,以下是具体实现:
方案一:自定义中间件(适用于所有请求场景)
中间件是ASP.NET Core请求管道的核心组件,能在路由匹配后、请求到达控制器前统一处理权限验证。
1. 实现中间件类
public class CustomerKeyValidationMiddleware { private readonly RequestDelegate _next; // 可注入你的权限服务,比如ICustomerPermissionService // private readonly ICustomerPermissionService _permissionService; public CustomerKeyValidationMiddleware(RequestDelegate next/*, ICustomerPermissionService permissionService*/) { _next = next; // _permissionService = permissionService; } public async Task InvokeAsync(HttpContext context) { // 从路由参数中提取customerkey if (context.GetRouteValue("customerkey") is int customerKey) { // 获取当前认证用户的唯一标识(需根据你的认证方式调整Claim类型) var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier); if (string.IsNullOrEmpty(userId)) { // 用户未认证,返回401 context.Response.StatusCode = StatusCodes.Status401Unauthorized; return; } // 替换为你的实际权限验证逻辑:检查用户是否有权访问该customerKey bool hasAccess = await CheckUserPermission(userId, customerKey); if (!hasAccess) { // 用户无权限,返回403 context.Response.StatusCode = StatusCodes.Status403Forbidden; return; } } // 验证通过,继续执行后续管道 await _next(context); } // 示例权限检查方法,实际需替换为你的业务逻辑(比如调用数据库或权限服务) private Task<bool> CheckUserPermission(string userId, int customerKey) { // 示例逻辑:此处可改为查询用户与客户的关联关系 // return _permissionService.HasAccessAsync(userId, customerKey); return Task.FromResult(true); } }
2. 注册中间件到请求管道
在Program.cs中,将中间件注册到路由匹配后、授权之后的位置,确保能获取路由参数和已认证用户信息:
var builder = WebApplication.CreateBuilder(args); // 添加MVC服务 builder.Services.AddControllersWithViews(); // 注册你的权限服务(如果需要) // builder.Services.AddScoped<ICustomerPermissionService, CustomerPermissionService>(); var app = builder.Build(); // 其他中间件(异常处理、HTTPS、静态文件等) if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); // 路由匹配 app.UseRouting(); // 认证与授权 app.UseAuthentication(); app.UseAuthorization(); // 注册自定义权限验证中间件 app.UseMiddleware<CustomerKeyValidationMiddleware>(); // 配置路由 app.MapControllerRoute( name: "ManagingCustomer", pattern: "{customerkey:int}/{controller=Home}/{action=Index}/{id?}"); app.MapControllerRoute( name: "Default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
方案二:MVC全局动作过滤器(仅针对控制器动作)
如果你的验证逻辑仅针对MVC控制器,可以使用全局动作过滤器,它更贴合MVC场景,能直接访问动作上下文。
1. 实现动作过滤器
public class CustomerKeyValidationFilter : IAsyncActionFilter { private readonly ICustomerPermissionService _permissionService; public CustomerKeyValidationFilter(ICustomerPermissionService permissionService) { _permissionService = permissionService; } public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // 从路由数据中提取customerkey if (context.RouteData.Values.TryGetValue("customerkey", out var customerKeyObj) && int.TryParse(customerKeyObj.ToString(), out int customerKey)) { var userId = context.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); if (string.IsNullOrEmpty(userId)) { // 返回未认证结果 context.Result = new UnauthorizedResult(); return; } // 调用权限服务验证 bool hasAccess = await _permissionService.HasAccessAsync(userId, customerKey); if (!hasAccess) { // 返回无权限结果 context.Result = new ForbidResult(); return; } } // 验证通过,继续执行动作 await next(); } } // 示例权限服务接口与实现 public interface ICustomerPermissionService { Task<bool> HasAccessAsync(string userId, int customerKey); } public class CustomerPermissionService : ICustomerPermissionService { public async Task<bool> HasAccessAsync(string userId, int customerKey) { // 替换为你的实际权限验证逻辑 return await Task.FromResult(true); } }
2. 注册全局过滤器
在Program.cs中,将过滤器添加到MVC选项的全局过滤器集合:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(options => { // 添加全局动作过滤器 options.Filters.Add<CustomerKeyValidationFilter>(); }); // 注册权限服务 builder.Services.AddScoped<ICustomerPermissionService, CustomerPermissionService>(); // 后续管道配置同方案一...
方案选择建议
- 如果需要对所有请求(包括非MVC请求)进行验证,选择中间件;
- 如果仅针对MVC控制器动作,选择全局动作过滤器,它提供更贴合MVC的上下文信息,处理逻辑更灵活。
内容的提问来源于stack exchange,提问作者Jason Butera
相关产品推荐
相关产品推荐

