2012-07-15 25 views
7

Implementé mi propio atributo de autorización personalizado en MVC 4 heredando de la clase AuthorizeAttribute. También tengo una personalizada ActionFilterAttribute. Ambos funcionan bien, pero el problema radica en ordenarlos. Necesito el filtro de acción personalizado para ejecutar antes del filtro de autorización personalizado.Cómo ejecutar Action Filter before Authorization Filter MVC 4

He intentado utilizar la propiedad Order para los atributos pero, según tengo entendido, Authorize Filters siempre se ejecutará antes de los filtros de acción.

¿Alguien sabe cómo forzar al filtro de acción a ejecutar antes del filtro de autorizaciones?

+0

El filtro Autorizar comprueba si el usuario tiene permiso, no tiene sentido comprobar nada más si no lo hacen. Parece que estás haciendo algo extraño. Quizás explicar por qué quieres cambiarlos. –

+0

Bueno, el filtro de acción comprueba si un usuario en particular tiene una contraseña temporal, por lo que quiero que se redireccione a la página "Cambiar contraseña" antes de que aparezca y dice "No autorizado". Espero que tenga sentido ... – davey1990

+1

En ese caso, parece que quieres que las personas con contraseñas temporales fallen aún con la comprobación Autorizar, pero simplemente quieren verificar en tu página "No autorizada" si tienen una contraseña temporal y redireccionar a la " Cambiar la página de Contraseña en ese caso. Alternativamente, podría detectar esto al iniciar sesión y obligarlos a cambiar su contraseña antes de permitirles iniciar sesión. Entonces no tienes que preocuparte. –

Respuesta

10

Cuando eche un vistazo al código fuente (disponible en http://aspnetwebstack.codeplex.com/) verá que esto no es posible con las clases de filtro estándar. Las implementaciones IAuthorizationFilter siempre se ejecutan antes de las implementaciones IActionFilter. Esto se debe a que los filtros de acción no se ejecutarán cuando los filtros de autorización arrojen un resultado.

Para resolver esto, puede crear su propia clase ControllerActionInvoker descendiente y anular la InvokeAction método:

public class MyControllerActionInvoker : ControllerActionInvoker 
{ 
    public override bool InvokeAction(ControllerContext controllerContext, string actionName) 
    { 
     // Your initialization code here 
     try 
     { 
      return base.InvokeAction(controllerContext, actionName); 
     } 
     finally 
     { 
      // Your finalization code here 
     } 
    } 
} 

que necesita inyectarse la clase personalizada MyControllerActionInvoker en sus controladores en una costumbre ControllerFactory clase:

public class MyControllerFactory : DefaultControllerFactory 
{ 
    private readonly MyControllerActionInvoker actionInvoker = new MyControllerActionInvoker(); 

    /// <summary> 
    /// Retrieves the controller instance for the specified request context and controller type. 
    /// </summary> 
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 
     var controllerInstance = base.GetControllerInstance(requestContext, controllerType); 

     if (controllerInstance != null) 
     { 
      var typedController = controllerInstance as Controller; 
      if (typedController != null) 
      { 
       typedController.ActionInvoker = this.actionInvoker; 
      } 
     } 

     return controllerInstance; 
    } 
} 

Y, por supuesto, ahora tiene que registrar su propio MyControllerFactory con el marco MVC. Debería hacer esto en donde también está registrando sus rutas:

var controllerFactory = new MyControllerFactory(); 
ControllerBuilder.Current.SetControllerFactory(controllerFactory); 

Esta implementación funciona bien aquí.