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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 11:50:24