根据操作名称授权用户

本文关键字:授权 用户 操作 | 更新日期: 2023-09-27 18:05:09

我有许多带有许多动作的控制器。每个动作都有自己的Role (Role name = 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中创建自定义AuthorizeAttribute)。. NET Core?)。问题是AuthorizationContext没有给我们关于用户试图到达的操作的信息。

我不想在每个动作上放置一个授权属性,有什么方法可以用新框架实现我的要求吗?(我更喜欢避免使用HttpContext。目前,它不适合管道架构)

根据操作名称授权用户

下面是执行自定义身份验证的一般过程。您的情况可能会在第一步中得到完全解决,因为您可以为角色添加一个Claim来修饰您的

1。通过为用户

创建标识来验证

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

public class MyAuthHandler : AuthenticationHandler<MyAuthOptions>
{
   protected override Task<AuthenticationTicket> 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<MyAuthOptions>
{
   public MyAuthMiddleware(
               RequestDelegate next,
               IDataProtectionProvider dataProtectionProvider,
               ILoggerFactory loggerFactory,
               IUrlEncoder urlEncoder,
               IOptions<MyAuthOptions> options,
               ConfigureOptions<MyAuthOptions> configureOptions)
         : base(next, options, loggerFactory, urlEncoder, configureOptions)
   {
   }
   protected override AuthenticationHandler<MyAuthOptions> CreateHandler()
   {
      return new MyAuthHandler();
   }
}
public static class MyAuthMiddlewareAppBuilderExtensions
{
   public static IApplicationBuilder UseMyAuthAuthentication(this IApplicationBuilder app, string optionsName = "")
   {
      return app.UseMiddleware<MyAuthMiddleware>(
         new ConfigureOptions<MyAuthOptions>(o => new MyAuthOptions()) { Name = optionsName });
   }
}

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

2。通过对标识

强制要求来授权

我们已经为用户创建了一个身份,但是我们仍然需要强制执行它。要做到这一点,我们需要像这样写一个AuthorizationHandler:

  public class MyAuthRequirement : AuthorizationHandler<MyAuthRequirement>, 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。将需求处理程序添加为授权策略

我们的身份验证需求仍然需要添加到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")]装饰我们的动作或控制器来强制执行这一要求。如果我们有许多控制器,每个控制器都有许多需要执行的操作,那么我们可能想要创建一个基类,并只装饰那个单一的控制器。

你的简单情况:

每个动作都有自己的Role (Role name = ControllerName)。actionName>)

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