asp.net core系列 51 Identity 授权(下)
原文:
asp.net core系列 51 Identity 授权(下)
1.6 基于资源的授权前面二篇中,熟悉了五种授权方式(对于上篇讲的策略授权,还有IAuthorizationPolicyProvider的自定义授权策略提供程序没有讲,后面再补充)。本篇讲的授权方式不是一种全新的授权方式,而是授权应用场景的灵活控制。 基于资源的授权是控制在 razor pages处理程序或mvc的action之中。资源:比如作者发表的文章,只有该作者才能更新文章,文章在进行授权评估之前,必须从数据存储中检索文章。 ? (1) 引用 IAuthorizationService 授权服务 授权作为实现IAuthorizationService服务并注册到服务集合的Startup类。 下面在mvc action中引用该接口,准备进行授权控制。 public class DocumentController : Controller { private readonly IAuthorizationService _authorizationService; private readonly IDocumentRepository _documentRepository; public DocumentController(IAuthorizationService authorizationService,IDocumentRepository documentRepository) { _authorizationService = authorizationService; _documentRepository = documentRepository; } } ? IAuthorizationService接口有二个 //重载1:指定资源resource和策略需求列表 Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user,object resource,IEnumerable<IAuthorizationRequirement> requirements); //重载2:指定资源resource和策略名称 Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user,string policyName); ? (2) 授权需求定义 基于 CRUD (创建、 读取、 更新、 删除) 的授权操作,使用OperationAuthorizationRequirement帮助器类,来提供一些授权名称。 /// <summary> ///授权四种需求Crud /// </summary> public static class Operations { public static OperationAuthorizationRequirement Create = new OperationAuthorizationRequirement { Name = nameof(Create) }; public static OperationAuthorizationRequirement Read = new OperationAuthorizationRequirement { Name = nameof(Read) }; public static OperationAuthorizationRequirement Update = new OperationAuthorizationRequirement { Name = nameof(Update) }; public static OperationAuthorizationRequirement Delete = new OperationAuthorizationRequirement { Name = nameof(Delete) }; } ? (3)?定义处理程序 /// <summary> /// 接口AuthorizationHandler<TRequirement,TResource> /// 使用OperationAuthorizationRequirement需求和Document资源 /// </summary> public class DocumentAuthorizationCrudHandler: AuthorizationHandler<OperationAuthorizationRequirement,Document> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,OperationAuthorizationRequirement requirement,Document resource) { //登录的当前用户是该文章作者,并且有读取权限。实际开发中从数据库读取TResource资源和requirement需求(需求这里是CRUD权限) //动态获取时,可以基于用户声明表UserClaim,也可以基于角色声明表RoleClaim,使用context.User.HasClaim?来判断 if (context.User.Identity?.Name == resource.Author && requirement.Name == Operations.Read.Name) { context.Succeed(requirement); } return Task.CompletedTask; } } ? (4)?Action中使用AuthorizeAsync验证授权 当用户登录后,要访问该文章页面时(/Document/index/1),使用AuthorizeAsync方法进行调用,确定当前用户是否允许查看提供的文章. /// <summary> /// /Document/index/1 /// </summary> /// <param name="documentId"></param> /// <returns></returns> public async Task<IActionResult> Index(int documentId) { Document Document = _documentRepository.Find(documentId); if (Document == null) { return new NotFoundResult(); } //使用AuthorizeAsync重载方法(1),来验证用户访问资源权限,条件是当前用户必需是[email?protected],因为是该用户的文章 var authorizationResult = await _authorizationService.AuthorizeAsync(User,Document,Operations.Read); //如果授权成功,则返回查看文档的页面 if (authorizationResult.Succeeded) { return View(); } //用户已通过身份验证,但授权失败 else if (User.Identity.IsAuthenticated) { return new ForbidResult(); } else { //Challenge:怀疑,返回重新执行身份认证,重定向到登录页 return new ChallengeResult(); } } ? (5) Document实体的定义和该实体仓储 public class Document { public string Author { get; set; } public byte[] Content { get; set; } public int ID { get; set; } public string Title { get; set; } } ? (6) 添加路由规则,和注入IAuthorizationService服务 services.AddSingleton<IAuthorizationHandler,DocumentAuthorizationCrudHandler>(); routes.MapRoute( name: "document", template: "{controller=Document}/{action=Index}/{documentId?}"); 最后当[email?protected]用户登录成功后,访问Document/index/1,查看该文章成功。 ? 总结:基于资源的授权,是应用在mvc的action 中或razor pages处理程序中,是区别之前的几种授权方式, 因为之前讲的授权是:启动程序时授权文件或文件夹,在控制器 action 和PageModel之上应用[Authorize]特性。 ? ?对于AuthorizeAsync重载方法(2)的使用案例查看官网文档,这里不在介绍。 思考:在实际开发项目中,处理资源如(增、删、改、查)权限,可以考虑本篇的基于资源的授权,但上面的示例需要改进,因为示例中定义的处理程序只针对Document资源,以及需求(指权限)是写死在处理程序中。如果要实现通用的资源授权,资源和需求权限需要从数据库中获取。例如考虑如下修改: //定义通用的TResource public class AuthorizationResource { public string UrlResource{get;set;} } //在index的action中修改 .AuthorizeAsync(User,new AuthorizationResource (){UrlResource="/Document/index/1" },Operations.Read); //处理程序修改,省略了授权逻辑处理(数据库获取需求和资源) public class DocumentAuthorizationCrudHandler: AuthorizationHandler<OperationAuthorizationRequirement,AuthorizationResource >
1.7 基于视图的授权? 在项目开发中,授权权限还需要控制页面,对页面的html进行显示或隐藏。需要在页面上使用授权服务依赖关系注入,若要将授权服务注入到 Razor 视图中,使用@inject指令。如果希望每个视图都能使用授权服务,需要将@inject指令插入?_ViewImports.cshtml的文件视图中。下面的视图授权控制是基于资源的授权。 @using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService
<!-- 指定策略名称 !--> @if ((await AuthorizationService.AuthorizeAsync(User,"PolicyName")).Succeeded) { <p>This paragraph is displayed because you fulfilled PolicyName.</p> } <!-- Model是指TResource !--> @if ((await AuthorizationService.AuthorizeAsync(User,Model,Operations.Edit)).Succeeded) { <p><a class="btn btn-default" role="button" href="@Url.Action("Edit","Document",new { id = Model.Id })">Edit</a></p> } 总结:视图中授权控制不能保证权限安全,还需要在action中实现授权服务。开源Github ? 参考文献 基于资源的授权 基于视图的授权 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – nhibernate配置和buildsessionfactory时间
- asp.net-mvc – ASP.NET MVC 3列表到IEnumerable
- Asp.Net Web Api基于令牌的授权,没有OWIN和AspNet.Identity
- asp.net-mvc – 区域内的Asp.Net MVC IgnoreRoute
- ASP.NET CORE(C#)与Spring Boot MVC(JAVA)
- 如何让ASP.NET AJAX通过GZip压缩发送JSON响应?
- 现在启动ASP.NET 5 Web项目还为时过早吗?
- asp.net-core – 配置ASP.Net Core以使用OIDC对Thinktectur
- asp.net – 在ascx文件中使用if条件
- asp.net – 如何调试w3wp clr.dll错误
- 通过asp.net中的C#将参数传递给CRYSTAL REPORT
- .NetCore技术研究-EntityFramework Core 3.0 Pre
- ASP.NET Core Web读取appsettings.json中的配置
- asp.net-mvc-3 – MVC 3不显眼的验证 – 有条件地
- asp.net-mvc – ASP.NET MVC 5 Web应用程序性能低
- asp.net – 如何使用MVC Razor设置类等html属性?
- .net – 如何跟踪和消除会话滥用?
- asp.net在Server.Transfer之后如何获取当前页面的
- asp.net – 没有配置验证处理程序来处理方案:自
- 自KB4338419以来,无法再从Classic ASP创建C#COM对