Pregunta

Hola, he podido usar la inyección de propiedades en mi FilterAttribute, sin embargo, me pregunto si es posible moverlo al constructor.

Mi código actual:

// AuthAttribute.cs

public class AuthAttribute : ActionFilterAttribute
{
    public Roles _authRoles { get; private set; }

    [Inject]
    private readonly IAuthorizationService _service;

    public AuthAttribute(Roles roles)
    {
        _authRoles = roles;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            string redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath;
            string redirectUrl = string.Format("?returnUrl={0}", redirectOnSuccess);
            string loginUrl = FormsAuthentication.LoginUrl + redirectUrl;

            filterContext.HttpContext.Response.Redirect(loginUrl, true);
        }
        else
        {
            bool isAuthorized = _service.Authorize(GetUserSession.Id, _authRoles.ToString());

            if (!isAuthorized)
            {
                // TODO: Make custom "Not Authorized" error page.
                throw new UnauthorizedAccessException("No access");
            }
        }
    }
}

 

// TestController.cs

[Auth(Roles.Developer)]
public ActionResult Index()
{
    // Some smart logic
}

¡Gracias por adelantado!

¿Fue útil?

Solución

No, esto no es posible como los parámetros para los constructores Debe ser tipos simples.

Para fines de prueba, podría tener otro constructor (ya que no debería usar un contenedor IOC con pruebas):

public class AuthAttribute : ActionFilterAttribute
{
    public Roles _authRoles { get; private set; }

    [Inject]
    private readonly IAuthorizationService _service;

    public AuthAttribute(Roles roles)
    {
        _authRoles = roles;
    }

    public AuthAttribute(Roles roles, IAuthorizationService authSvc)
        : this(roles)
    {
        this.service = authSvc;
    }

    // ...
}

Otros consejos

Inyección de constructor es posible en este escenario, pero debe usar un combo de atributo/filtro.

Su implementación de filtro (ex .: iauthorizationFilter) utilizará la inyección de constructor y hará todo el trabajo ...

Su atributo (Ex.: FilterAttribute) será delgado, se utilizará principalmente para decorar sus controladores o acciones.

public class AuthorizationFilter : IAuthorizationFilter
{
    private readonly IAuthorizationService _authorizationService;
    private readonly UserRoles _requiredRoles; // Enum of Roles

    public AuthorizationFilter(IAuthorizationService authorizationService, UserRoles requiredRoles)
    {
        _authorizationService = authorizationService;
        _requiredRoles = requiredRoles;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        // do work, or HandleUnauthorizedRequest()
    }

    protected void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        // do work
    }

}

public class RequireRolesAttribute : FilterAttribute
{
    public readonly UserRoles RequiredRoles;

    public RequireRolesAttribute(UserRoles requiredRoles)
    {
        RequiredRoles = requiredRoles;
    }        
}

Luego, su contenedor ninject ata el atributo al filtro:

// controller-level
kernel.BindFilter<AuthorizationFilter>(FilterScope.Controller, 0).WhenControllerHas<RequireRolesAttribute>()
// action level
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0).WhenActionMethodHas<RequireRolesAttribute>();

Ver:

Inyección de dependencia con atributo Ninject y Filtro para ASP.NET MVC

Atributo de unión de Ninject para filtrar con argumentos de constructor

https://github.com/ninject/ninject.web.mvc/wiki/filter-configurations

El truco que busco superar es cómo se definen mis roles en el atributo al filtro ... la documentación ninguno debería ayudar, pero todavía no estoy allí.

Buena suerte.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top