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

如何在ControllerBase中统一实现用户授权以避免控制器动作代码重复?

在自定义BaseController中统一实现前置授权逻辑

你可以通过重写ControllerBase的**OnActionExecuting**方法来实现全局前置授权,避免在每个Action中重复编写代码。这个方法会在控制器的Action执行前触发,刚好适合做统一的授权校验。

具体实现步骤

1. 定义带授权逻辑的自定义BaseController

在自定义基类中注入你的dbService,然后重写OnActionExecuting方法,把授权校验逻辑放在这里:

public class CustomBaseController : ControllerBase
{
    private readonly IDbService _dbService;

    // 通过构造函数注入dbService
    public CustomBaseController(IDbService dbService)
    {
        _dbService = dbService;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // 跳过带有[AllowAnonymous]特性的Action授权校验
        var hasAllowAnonymous = context.ActionDescriptor.EndpointMetadata
            .Any(m => m is AllowAnonymousAttribute);
        if (hasAllowAnonymous)
        {
            base.OnActionExecuting(context);
            return;
        }

        // 执行你的授权逻辑
        var userItem = _dbService.GetAuthorizedUser(User);
        if (userItem == null)
        {
            // 授权失败时直接返回Unauthorized结果,终止后续Action执行
            context.Result = Unauthorized(ResponseMessage.UnAuthorized);
            return;
        }

        // 如果需要在后续Action中使用授权后的userItem,可以存在HttpContext.Items里
        HttpContext.Items["AuthorizedUser"] = userItem;

        // 继续执行后续流程
        base.OnActionExecuting(context);
    }
}

2. 让业务控制器继承自定义基类

后续的业务控制器只需要继承CustomBaseController,自动获得前置授权能力:

public class FooController : CustomBaseController
{
    // 构造函数需要传递dbService给基类
    public FooController(IDbService dbService) : base(dbService)
    {
    }

    [HttpGet]
    public IActionResult GetData()
    {
        // 如果需要使用授权后的用户信息,从HttpContext.Items中获取
        var authorizedUser = HttpContext.Items["AuthorizedUser"] as UserItem;
        
        // 编写你的业务逻辑
        return Ok("数据内容");
    }

    // 示例:带有[AllowAnonymous]的Action会跳过授权校验
    [HttpGet]
    [AllowAnonymous]
    public IActionResult PublicData()
    {
        return Ok("公开数据");
    }
}

可选方案:自定义Action过滤器

如果你不想依赖基类继承,也可以用自定义Action过滤器来实现相同逻辑,灵活性更高:

1. 定义授权过滤器

public class CustomAuthorizationFilter : IActionFilter
{
    private readonly IDbService _dbService;

    public CustomAuthorizationFilter(IDbService dbService)
    {
        _dbService = dbService;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // 检查是否允许匿名访问
        var hasAllowAnonymous = context.ActionDescriptor.EndpointMetadata
            .Any(m => m is AllowAnonymousAttribute);
        if (hasAllowAnonymous) return;

        var controller = context.Controller as ControllerBase;
        if (controller == null) return;

        var userItem = _dbService.GetAuthorizedUser(controller.User);
        if (userItem == null)
        {
            context.Result = controller.Unauthorized(ResponseMessage.UnAuthorized);
            return;
        }

        context.HttpContext.Items["AuthorizedUser"] = userItem;
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // 这里可以写Action执行后的后置逻辑(可选)
    }
}

2. 注册并使用过滤器

  • 全局注册(所有控制器生效):在Program.cs中添加:
builder.Services.AddScoped<CustomAuthorizationFilter>();
builder.Services.AddControllers(options =>
{
    options.Filters.Add<CustomAuthorizationFilter>();
});
  • 或只在自定义基类上标记(继承基类的控制器生效):
[ServiceFilter(typeof(CustomAuthorizationFilter))]
public class CustomBaseController : ControllerBase
{
}

内容的提问来源于stack exchange,提问作者A Farmanbar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 17:20:48