returns remarks c# asp.net asp.net-core asp.net-core-mvc

c# - remarks - Autorizar a un usuario en función del nombre de la acción.



remarks c# documentation (1)

Tengo muchos controladores con muchas acciones. Cada acción tiene su propio rol (nombre de rol = nombre_controlador.acciónNombre).

En versiones anteriores, podría probar si el usuario actual puede acceder o no a una acción utilizando un AuthorizeAttribute "genérico":

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); }

Con la versión asp.net 5, he descubierto que necesito usar los requisitos ( ¿Cómo se crea un AuthorizeAttribute personalizado en ASP.NET Core? ). El problema es que el AuthorizationContext no nos da la información sobre la acción que el usuario está tratando de realizar.

No quiero poner un atributo de Autorización en cada acción, ¿hay alguna forma de cumplir mi requisito con el nuevo marco? (Prefiero evitar el uso de HttpContext.Current, no encaja bien en una arquitectura de tubería)


Aquí está el proceso general para imponer la autenticación personalizada. Su situación puede resolverse completamente en el paso uno, ya que podría agregar un Reclamo por el rol que decora su

1. Autenticarse creando una identidad para el usuario.

Escribir middleware e insertarlo en la tubería a través de IApplicationBuilder.UseMiddleware<> es cómo se realiza la autenticación personalizada. Aquí es donde extraemos la información que pueda ser necesaria más adelante para la autorización y la ClaimsIdentity en una ClaimsIdentity . Aquí tenemos un HttpContext para poder obtener información del encabezado, las cookies, la ruta solicitada, etc. Aquí hay un ejemplo:

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 }); } }

Para utilizar este middleware, inserte esto en Startup.Configure antes del enrutamiento: app.UseMyAuthAuthentication();

2. Autorizar mediante el cumplimiento de requisitos sobre la identidad.

Hemos creado una identidad para el usuario, pero todavía tenemos que hacerla cumplir. Para hacer esto necesitamos escribir un AuthorizationHandler como este:

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. agregar el controlador de requisitos como una política de autorización

Nuestro requisito de autenticación aún debe agregarse a Startup.ConfigureServices para que se pueda utilizar:

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

4. Utilizar la política de autorización.

El paso final es hacer cumplir este requisito para acciones específicas decorando nuestra acción o controlador con [Authorize("MyAuth")] . Si tenemos muchos controladores, cada uno con muchas acciones que requieren cumplimiento, entonces podemos querer hacer una clase base y decorar ese único controlador.

Tu situación más simple:

Cada acción tiene su propia función (nombre de la función = nombreDeControl.actualización>)

Si ya tiene todas sus acciones ajustadas con [Authorize(Roles = "controllername.actionname")] entonces probablemente solo necesite la parte # 1 arriba. Solo agregue un nuevo Claim(ClaimTypes.Role, "controllername.actionname") que sea válido para la solicitud en particular.