前两篇文章扫盲篇,进阶篇中介绍了基本的asp.net core 中基于策略的授权的使用方法。
使用策略授权时,只能指定策略,不能配置其他信息。
1 2 3 4 5 | [Authorize(Policy = "AtLeast21" )] //指定要验证的策略 public class AlcoholPurchaseController : Controller { public IActionResult Index() => View(); } |
如果我们有很多种授权逻辑,就要有很多种策略。有没有一种可能,可以在指定授权策略时,传入一些参数,灵活的控制授权呢。
当然是可以的。
我们包装一个自己的验证特性PermissionAuthorizeAttribute类,继承自AuthorizeAttribute。构造函数允许传入权限类型参数,并且执行父类构造函数时指定策略“Permission”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /// <summary> /// 继承自AuthorizeAttribute,AuthorizeAttribute要求指定策略,那这里就固定为Permission。 /// 支持接受一个权限集合(Permission[]),可以指定要验证的权限 /// </summary> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true )] public class PermissionAuthorizeAttribute : AuthorizeAttribute { /// <summary> /// </summary> /// <param name="permissions"></param> public PermissionAuthorizeAttribute( params Permission[] permissions) : base ( "Permission" ) => Permissions = permissions; public Permission[] Permissions { get ; set ; } } |
权限类型是一个枚举,标记什么样的权限,这里就简单的做个示例。允许传入多个,应该是or的关系。如果要验证多个权限类型,是并且的关系。那应该加多个特性。
1 2 3 4 5 6 7 8 9 10 11 12 | public enum Permission { /// <summary> /// 用户有明细 /// </summary> HasName = 1, /// <summary> /// 用户有邮箱 /// </summary> HasEmail = 2, } |
使用的时候如下,可以看到访问HasNameController时,授权校验了Permission.HasName权限。
1 2 3 4 5 6 7 8 9 10 11 12 | [PermissionAuthorize(Permission.HasName)] public class HasNameController : Controller { public IActionResult Index() => View(); } [PermissionAuthorize(Permission.HasEmail)] public class HasEmailController : Controller { public IActionResult Index() => View(); } |
那么handler中怎么拿到权限类型信息呢?我们知道handler校验函数有两个参数,一个是TRequirement,startup类中配置策略时创建的,这个是固定的。一个是AuthorizationHandlerContext,上下文。听听,上下文,就感觉应该从这里拿。
AuthorizationHandlerContext有个Resource属性,解释是“The optional resource to evaluate the Requirements against.”要对Requirements进行评估的可选资源。我理解如果你验证特性放在controller上,Resource就是这个controller。如果你验证特性放在action上,Resource就是这个action。我们使用在controller上了,那么我们就可以通过controller对象找到其上面的特性信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { var attributes = new List<PermissionAuthorizeAttribute>(); if ((context.Resource as RouteEndpoint) is RouteEndpoint route) { //通过元数据Metadata能找到其上的PermissionAuthorizeAttribute特性实例 var tempAttributes = route.Metadata.Where(x => x is PermissionAuthorizeAttribute); if (tempAttributes != null && tempAttributes.Count() > 0) { attributes.AddRange(tempAttributes.Select(x => (PermissionAuthorizeAttribute)x)); } } //特性实例上的Permissions信息 var permissions = attributes.Select(x => x.Permissions); //后面就是自己的验证逻辑了 foreach ( var item in permissions) { if (item.Any(x => x == Permission.HasName) && !context.User.HasClaim(c => c.Type == ClaimTypes.Name)) { context.Fail(); return Task.CompletedTask; } if (item.Any(x => x == Permission.HasEmail) && !context.User.HasClaim(c => c.Type == ClaimTypes.Email)) { context.Fail(); return Task.CompletedTask; } } context.Succeed(requirement); return Task.CompletedTask; } } |
startup正常注册就行
1 2 3 4 5 6 7 8 9 | services.AddAuthorization(options => { options.AddPolicy( "Permission" , policy => policy.Requirements.Add( new PermissionRequirement())); }); services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>(); |
来自:https://blog.csdn.net/yangguosheng/article/details/129169277
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!