asp.net-mvc – ASP.NET Core中基于活动的授权
我们有一个asp.net mvc应用程序,我正在移植到aspnet核心mvc.
在旧解决方案中,使用 Windows身份验证完成身份验证. 最重要的是,我们有一个“基于活动的身份验证”(如http://ryankirkman.com/2013/01/31/activity-based-authorization.html);用户连接到角色,角色连接到权限.用户角色和相应的权限存储在单独的应用程序中,该应用程序用作我们的应用程序和少数其他系统的授权服务. 对授权服务api查询用户“Jon Doe”的权限会得到如下响应: { Email:"Jon.Doe@acme.com",FirstName:"Jon",LastName:"Doe",Resources: [ "CanAccessWebApplication","CanCopyAppointment","CanEditAppointment","CanEditContact","CanSaveContact" ... ] Alias:"1234567",UserId:"1234" } 在我们当前的应用程序中,使用控制器方法上的属性(我们已经实现了自己)来检查这些权限: public ContactController { [ActionUserAccess("CanSaveContact")] public ActionResult SaveContact { ... } } ActionUserAccessAttribute过滤器的当前遗留实现如下所示: [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] public sealed class ActionUserAccessAttribute : ActionFilterAttribute { private readonly string _accessRight; public ActionUserAccessAttribute(string accessRight) { _accessRight = accessRight; } public override void OnActionExecuting(ActionExecutingContext filterContext) { if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { throw new InvalidOperationException("ActionUserAccessAttribute can not be used for controllers or actions configured for anonymous access"); } base.OnActionExecuting(filterContext); var securityService = ContainerResolver.Container.GetInstance<ISecurityService>(); var hasResource = securityService.HasAccess(_accessRight); if (!hasResource) { filterContext.Result = new HttpStatusCodeResult( 403,string.Format( "User {0} is not authorized to access the resource:'{1}' ",filterContext.HttpContext.User.Identity.Name,_accessRight)); } } } } 将属性/过滤器移植到aspnetcore似乎非常简单,但根据这个答案https://stackoverflow.com/a/31465227/1257728“asp.net security person”@blowdart我们不应该这样做. 如果没有将自定义过滤器移植到aspnetcore,那么最适合在这里实现的是什么? [Authorize(Roles = "CanSaveContact")] public ActionResult Save() 这种方法的错误在于,这不是关于角色,而是关于访问权限的更多信息. 我还查看了基于策略的授权: https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies 在控制器中看起来像这样: [Authorize(Policy = "CanSaveContact")] public ActionResult Save() 但是,当我阅读上面基于微软政策的示例中的代码时,我必须将安全服务api中存在的所有可用访问权限添加为Startup类的ConfigureService方法中的策略,以便能够使用它们.我觉得好像很尴尬(伪代码): public void ConfigureServices(IServiceCollection services) { services.AddMvc(); IEnumerable<string> allAccessRights = _securtiyService.GetAllAccessRights(); services.AddAuthorization(options => { foreach(var accessRight in allAccessRights) { options.AddPolicy(accessRight,policy => policy.Requirements.Add(new AccessRightRequirement(accessRight)); } }); services.AddSingleton<IAuthorizationHandler,AccessRightHandler>(); } 然后,AccessRightHandler可以用于验证用户的访问权限.编写AccessRightHandler是可以的,但似乎没有必要将所有权限添加为策略. 在我们的aspnetcore应用程序中实现此类授权的最佳方法是什么? 解决方法
很好的问题,我认为很多人在升级到ASP.NET Core时会遇到同样的问题.
Barry Dorrans(@blowdart)是绝对正确的,你不应该编写自己的自定义授权属性 – ASP.NET Core中的授权已经大大改进,你绝对可以根据自己的需要进行创建. 它当然在很大程度上取决于您当前的应用程序,以及您拥有的角色,因此我将基于您在上面提供的代码段做出一些假设. 在开始之前,我真的建议你阅读新的Authorization docs for ASP.NET Core,以及Barry Dorran在GitHub上的Authorization workshop.我强烈建议你通过后者,他也有一个.NET Core 2.0分支. 根据您的实现方式,您可以使用基于声明的授权,也可以使用基于资源的授权. 看看你的角色,看起来像基于资源的auth实际上可以在你的情况下工作得很好! 例如: 确定可能的操作(操作名称将从您的资源中获取): public static class Operations { public static OperationAuthorizationRequirement Access = new OperationAuthorizationRequirement { Name = "Access" }; public static OperationAuthorizationRequirement Copy = new OperationAuthorizationRequirement { Name = "Copy" }; public static OperationAuthorizationRequirement Edit = new OperationAuthorizationRequirement { Name = "Edit" }; public static OperationAuthorizationRequirement Save = new OperationAuthorizationRequirement { Name = "Save" }; public static OperationAuthorizationRequirement Delete = new OperationAuthorizationRequirement { Name = "Delete" }; } 创建基本资源授权处理程序: public abstract class BaseResourceAuthorizationHandler<TResource> : AuthorizationHandler<OperationAuthorizationRequirement,TResource> { private readonly string _resourceType; public BaseResourceAuthorizationHandler(string resourceType) { _resourceType = resourceType; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,OperationAuthorizationRequirement requirement,TResource resource) { if (context.User.HasClaim("Resources",$"Can{requirement.Name}{_resourceType}")) { context.Succeed(requirement); } return Task.CompletedTask; } } 实现基于资源的特定处理程序.资源是应用程序中绑定对象到资源中的实体.此类将成为当前资源角色,Operations和ASP.NET Core中的授权系统之间的粘合剂.这些也可以扩展为为任何特定资源类型/操作添加额外的逻辑 public class AppointmentAuthorizationHandler : BaseResourceAuthorizationHandler<Appointment> { public AppointmentAuthorizationHandler() : base("Appointment") { } } 然后你注册: services.AddSingleton<IAuthorizationHandler,AppointmentAuthorizationHandler>(); 然后在你的控制器中: public class AppointmentsController : Controller { IAppointmentsRepository _appointmentsRepository; IAuthorizationService _authorizationService; public AppointmentsController(IAppointmentsRepository appointmentsRepository,IAuthorizationService authorizationService) { _appointmentsRepository = appointmentsRepository; _authorizationService = authorizationService; } public IActionResult Edit(int id) { var appointment = _appointmentsRepository.Get(id); if (appointment == null) { return new NotFoundResult(); } if (!(await _authorizationService.AuthorizeAsync(User,appointment,Operations.Edit))) { return new ChallengeResult(); } return View(appointment); } } 您也可以在视图中执行相同操作,以检查是否允许用户查看“编辑”按钮,例如: @using Microsoft.AspNetCore.Authorization @model IEnumerable<Appointment> @inject IAuthorizationService AuthorizationService <h1>Document Library</h1> @foreach (var appointment in Model) { if (await AuthorizationService.AuthorizeAsync(User,Operations.Edit)) { <p>@Html.ActionLink("Appointment #" + appointment.Id,"Edit",new { id = appointment.Id })</p> } } 附:只是添加一个注释 – 是的,你失去了按属性过滤的能力,但最终这种方式更好.首先 – 您远离基于字符串的角色,您根据操作类型和资源类型请求权限.其次,您可以以更好(和智能的方式)处理权限,以及组合多个权限检查. 它看起来更复杂,但它也更强大:) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- .net – 关于强名称验证跳过的奇怪问题
- asp.net-core-mvc – 使用RenderBody()的UTF-8中的特殊字符
- asp.net-core-2.0 – 如何在Razor Pages中使用单独的BindPr
- asp.net核心 – ASP.Net MVC 6中使用Tag Helpers的优点是什
- asp.net-mvc – 使用ASP.NET MVC的基础认证
- 【FastDFS】FastDFS和asp.net项目的结合
- asp.net-mvc – Asp.net MVC中的TimeSpan和“24:00”解析错
- asp.net – WSFederationAuthenticationModule.Redirecting
- [ASP.NET MVC]如何设定Area底下的页面为起始页(网址路由Rou
- entity-framework – 带有INT id列的MVC 6的ASP.Net标识