¿Es posible ejecutar todos los controladores para una política en línea en lugar de con un atributo?

8

En la mayoría de mis API, simplemente hago una autorización como esta:

[Authorize(Policy = "Foo")]
public MyApi()

Sin embargo, obtengo esta política de un NuGet y no puedo modificarla.

Para algunas de mis API, no siempre quiero tener esta política. Esto necesita ser resuelto en tiempo de ejecución basado en alguna configuración. Me gustaría alguna forma de ejecutar esto en línea y asegurarme de que se ejecuten todos los controladores que están configurados.

Después de muchas búsquedas, descubrí que creo un IAuthorizationServicey lo uso para llamar AuthorizeAsync. Parece que es lo que quiero, pero el problema con el que me encuentro ahora es que todos los controladores dependen de un AuthorizationFilterContextrecurso como contexto. Esto parece suceder automáticamente cuando la Autorización se realiza a través del atributo, pero no a través de la llamada a AuthorizeAsync. Debe pasarse manualmente en este caso. Mi código ahora se ve así:

public MyApi()
{
    var allowed = await _authorizationService.AuthorizeAsync(User, null, "Foo").ConfigureAwait(false);
}

Esto parece pasar por todos mis controladores correctamente, pero no funcionan debido a que faltan AuthorizationFilterContext.

1) ¿Es este el enfoque correcto para empezar, o hay alguna otra forma de hacerlo en línea? Supongo que probablemente haya alguna forma de crear mi propia política que envuelva esta y puedo verificar la configuración allí, pero si hay un enfoque simple en línea, preferiría eso.

2) Si esta forma es válida, ¿hay una buena manera de obtenerla AuthorizationFilterContext? He intentado crearlo manualmente, pero me temo que esto no es correcto sin pasar más datos del contexto, pero no puedo encontrar ningún buen ejemplo / documento:

new AuthorizationFilterContext(new ActionContext(HttpContext, HttpContext.GetRouteData(), new ActionDescriptor()), new IFilterMetadata[] { });

usuario3715648
fuente
Esta es una muy mala manera de hacerlo. En primer lugar, cualquier llamada puede afectar su método de API ahora a pesar de que no tienen acceso para él porque usted hace la verificación de acceso en un momento posterior. Cree un atributo personalizado para usted y puede verificar fácilmente la política (individual o múltiple) que desea verificar que pertenece al usuario o no. También es bueno leer esto: docs.microsoft.com/en-us/aspnet/ núcleo / seguridad / autorización / ...
curiousBoy

Respuestas:

-2

No habrá AuthorizationFilterContextcuando esté fuera de la canalización de autorización. Por lo tanto, no debe manejar la autenticación en línea con IAuthorizationService.

Esto parece pasar por todos mis controladores correctamente, pero no funcionan debido a que faltan AuthorizationFilterContext.

Parece que tienes el control sobre los controladores de autenticación. ¿Has probado la autenticación de cortocircuito dentro del controlador si no es necesario?

El controlador puede obtener servicios a través de la DI para que pueda poner su configuración de tiempo de ejecución requerida a través de IOptions o IHttpContextAccessor y lo que sea.

Sebastian
fuente
-2

¿No puede crear su propio Authorizeatributo que heredaría el actual y resolvería la política internamente? O incluso mejor intente usarIAuthorizationPolicyProvider

class MyPolicyProvider : IAuthorizationPolicyProvider
{
    private DefaultAuthorizationPolicyProvider BackupPolicyProvider { get; }

    public MyPolicyProvider()
    {
        BackupPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
    }

    public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        if (policyName.Equals("Foo"))
        {
            bool myConditionToAvoidPolicy = true;
            if (myConditionToAvoidPolicy)
            {
                return Task.FromResult<AuthorizationPolicy>(null);
            }
        }

        return BackupPolicyProvider.GetPolicyAsync(policyName);
    }
}

Esto no se ha probado, pero puede encontrar más información al respecto aquí .

zhuber
fuente
-2

Parece que su condición de verificación ocurre en un momento posterior, lo que no creo que sea una buena idea. Su método de API es vulnerable y aún está abierto a medida que su verificación se realiza en un momento posterior. Pero al usar el atributo puede capturarlo en un nivel anterior y aún puede aplicar la lógica personalizada. Al final del día, todo lo que decide es "¡sí, tener acceso" o "no, no hay acceso para ti!" A continuación no se ha probado, pero debería comenzar:

public class CustomAuthorize : AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var currentIdentity = System.Threading.Thread.CurrentPrincipal.Identity;
        if (!currentIdentity.IsAuthenticated) {
            // no access
        }

        bool myCondition = "money" == "happiness"; 
        if(myCondition){
           // do your magic here...
        }
        else{
          // another magic...
       }           
    }
}
curioso
fuente