根据操作名称授权用户

我有很多控制器有很多动作。 每个操作都有自己的角色(角色名称= ControllerName.actionName)。

在以前的版本中,我可以测试当前用户是否可以使用“通用”AuthorizeAttribute访问操作:

public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext) { string currentAction = actionContext.ActionDescriptor.ActionName; string currentController = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName; Roles = (currentController + "." + currentAction).ToLower(); base.OnAuthorization(actionContext); } 

使用asp.net 5版本,我发现我需要使用需求( 如何在ASP.NET Core中创建自定义AuthorizeAttribute? )。 问题是AuthorizationContext没有向我们提供有关用户尝试访问的操作的信息。

我不想在每个操作上放置一个Authorize属性,有没有办法用新框架实现我的要求? (我更喜欢避免使用HttpContext.Current,它不适合管道架构)

以下是实施自定义身份validation的一般过程。 您的情况可能在第一步中完全解决,因为您可以为装饰您的角色添加声明

1.通过为用户创建身份进行身份validation

编写中间件并通过IApplicationBuilder.UseMiddleware<>将其插入管道是自定义身份validation的完成方式。 这是我们提取授权后可能需要的任何信息的地方,并将其置于ClaimsIdentity 。 我们这里有一个HttpContext ,所以我们可以从标题,cookie,请求的路径等中获取信息。这是一个例子:

 public class MyAuthHandler : AuthenticationHandler { protected override Task HandleAuthenticateAsync() { // grab stuff from the HttpContext string authHeader = Request.Headers["Authorization"] ?? ""; string path = Request.Path.ToString() ?? ""; // make a MyAuth identity with claims specifying what we'll validate against var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Authentication, authHeader), new Claim(ClaimTypes.Uri, path) }, Options.AuthenticationScheme); var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), new AuthenticationProperties(), Options.AuthenticationScheme); return Task.FromResult(ticket); } } public class MyAuthOptions : AuthenticationOptions { public const string Scheme = "MyAuth"; public MyAuthOptions() { AuthenticationScheme = Scheme; AutomaticAuthentication = true; } } public class MyAuthMiddleware : AuthenticationMiddleware { public MyAuthMiddleware( RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, IUrlEncoder urlEncoder, IOptions options, ConfigureOptions configureOptions) : base(next, options, loggerFactory, urlEncoder, configureOptions) { } protected override AuthenticationHandler CreateHandler() { return new MyAuthHandler(); } } public static class MyAuthMiddlewareAppBuilderExtensions { public static IApplicationBuilder UseMyAuthAuthentication(this IApplicationBuilder app, string optionsName = "") { return app.UseMiddleware( new ConfigureOptions(o => new MyAuthOptions()) { Name = optionsName }); } } 

要使用此中间件,请在路由之前在Startup.Configure插入: app.UseMyAuthAuthentication();

2.通过强制执行身份要求进行授权

我们已经为用户创建了一个标识,但我们仍然需要强制执行它。 为此,我们需要编写一个这样的AuthorizationHandler

  public class MyAuthRequirement : AuthorizationHandler, IAuthorizationRequirement { public override void Handle(AuthorizationContext context, MyAuthRequirement requirement) { // grab the identity for the MyAuth authentication var myAuthIdentities = context.User.Identities .Where(x => x.AuthenticationType == MyAuthOptions.Scheme).FirstOrDefault(); if (myAuthIdentities == null) { context.Fail(); return; } // grab the authentication header and uri types for our identity var authHeaderClaim = myAuthIdentities.Claims.Where(x => x.Type == ClaimTypes.Authentication).FirstOrDefault(); var uriClaim = context.User.Claims.Where(x => x.Type == ClaimTypes.Uri).FirstOrDefault(); if (uriClaim == null || authHeaderClaim == null) { context.Fail(); return; } // enforce our requirement (evaluate values from the identity/claims) if ( /* passes our enforcement test */ ) { context.Succeed(requirement); } else { context.Fail(); } } } 

3.添加需求处理程序作为授权策略

我们的身份validation要求仍需要添加到Startup.ConfigureServices以便可以使用它:

 // add our policy to the authorization configuration services.ConfigureAuthorization(auth => { auth.AddPolicy(MyAuthOptions.Scheme, policy => policy.Requirements.Add(new MyAuthRequirement())); }); 

4.使用授权政策

最后一步是通过使用[Authorize("MyAuth")]装饰我们的操作或控制器来强制执行特定操作的此要求。 如果我们有许多控制器,每个控制器都有许多需要执行的操作,那么我们可能想要创建一个基类并只装饰那个单一的控制器。

你更简单的情况:

每个操作都有自己的角色(角色名称= ControllerName.actionName>)

如果您已经使用[Authorize(Roles = "controllername.actionname")]对所有操作进行了微调,那么您可能只需要上面的第1部分。 只需添加一个对特定请求有效的新Claim(ClaimTypes.Role, "controllername.actionname")