在ServiceStack OrmLite中重写AuthenticateAttribute的ExecuteAsync无效问题排查
解决ServiceStack自定义权限属性ExecuteAsync不执行的问题
问题根源
ServiceStack的AuthenticateAttribute和RequiredPermissionAttribute在.NET MVC控制器中是作为**MVC授权过滤器(Authorization Filter)**工作的,而非ServiceStack自身Service接口的请求过滤器。MVC的过滤器管道不会调用ServiceStack定义的ExecuteAsync方法,而是触发MVC标准Filter接口的方法(如IAsyncAuthorizationFilter.OnAuthorizationAsync),这就是你重写的ExecuteAsync从未执行的核心原因。
正确实现方式
自定义权限属性需要实现MVC的异步授权过滤器接口IAsyncAuthorizationFilter,在OnAuthorizationAsync方法中整合ServiceStack内置权限校验与你的自定义扩展权限逻辑。这样既保留ServiceStack原生权限校验的能力,又能针对admin区域等特定场景执行额外权限检查。
代码示例
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using ServiceStack; using ServiceStack.Auth; using ServiceStack.Data; public class CustomRequiredPermissionAttribute : RequiredPermissionAttribute, IAsyncAuthorizationFilter { public CustomRequiredPermissionAttribute(params string[] permissions) : base(permissions) { } public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { // 先执行ServiceStack内置的权限校验逻辑 var request = context.HttpContext.RequestServices.GetRequiredService<IRequest>(); await base.ExecuteAsync(request, null); // 针对admin区域执行扩展权限校验 var isAdminArea = context.RouteData.Values["area"]?.ToString()?.Equals("Admin", StringComparison.OrdinalIgnoreCase) ?? false; if (!isAdminArea) return; // 获取自定义会话对象 var session = request.SessionAs<CustomAuthUserSession>(); if (session == null) { context.Result = new ForbidResult(); return; } // 这里实现你的扩展权限查询逻辑(比如从数据库获取) using var db = context.HttpContext.RequestServices.GetRequiredService<IDbConnectionFactory>().OpenDbConnection(); var userExtraPermissions = await db.SingleByIdAsync<UserExtraPermissions>(session.UserAuthId); if (userExtraPermissions == null || !userExtraPermissions.HasAdminExtendedAccess) { context.Result = new ForbidResult(); } } } // 示例:自定义会话类 public class CustomAuthUserSession : AuthUserSession { // 你的自定义会话字段 } // 示例:存储扩展权限的实体类 public class UserExtraPermissions { public string Id { get; set; } public bool HasAdminExtendedAccess { get; set; } }
关键说明
- 无需额外注册该属性,直接标注在MVC控制器或Action方法上即可生效。
- 通过
request.SessionAs<CustomAuthUserSession>()获取自定义会话对象,避免重复查询。 - 仅在admin区域触发扩展权限校验,符合你“避免不必要数据库查询”的需求。
内容的提问来源于stack exchange,提问作者Irish Yobbo
相关产品推荐
相关产品推荐

