2010-04-05 13 views
44

[Authorize] atributo es agradable y práctico invención EM, y espero que pueda resolver los problemas que tengo ahoraCómo hacer Autorizar atributo volver encargo 403 página de error en lugar de redireccionar a la página de inicio de sesión

Para ser más específicos:

Cuando el cliente actual no está autenticado - [Authorize] redirige desde la acción segura a la página de inicio de sesión y después de que el inicio de sesión fue exitoso - devuelve al usuario, esto es bueno.

Pero cuando el cliente actual ya está autenticado pero no está autorizado para ejecutar una acción específica, todo lo que necesito es simplemente mostrar mi página general 403.

¿Es posible sin mover la lógica de autorización dentro del cuerpo del controlador?

actualización: El comportamiento que necesito en debe ser semánticamente es igual a este bosquejo:

public ActionResult DoWork() 
{ 
    if (!NotAuthorized()) 
    { 
     // this should be not redirect, but forwarding 
     return RedirectToAction("403");   
    } 

    return View(); 
} 

así - no debe sin ninguna redirección y url debe permanecer igual, pero el contenido de la página debe ser reemplazado con 403 páginas

actualización 2: he implementado boceto de esta manera:

[HandleError] 
public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     ViewData["Message"] = "Welcome to ASP.NET MVC!"; 

     return View(); 
    } 

    [CustomActionFilter] 
    public ActionResult About() 
    { 
     return View(); 
    } 

    public ActionResult Error_403() 
    { 
     return Content("403"); 
    } 
} 

public class CustomActionFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     filterContext.Result = new ContentResult { Content = "403" }; 
    } 
} 

y no puede obtener la forma de ejecución adecuadamente hacia adelante a HomeController.Action_403() por lo que mostrar 403.

Actualización 3:

filterContext.Result = new ViewResult() { ViewName = "Error_403" }; 

por lo que esta es una respuesta en el modo de hacer específica ver plantilla ... pero todavía no tengo idea de cómo ejecutar otro controlador, de todos modos, es una solución bastante buena.

+0

@casperOne: ¿por qué demonios que haya añadido el comentario, ya que era de mi persona ??? – zerkms

+0

El comentario en el lado dificulta la legibilidad del código. Colocarlo arriba evita que aparezcan las barras de desplazamiento, y es solo parte del proceso de limpieza. – casperOne

+0

@casperOne: soy un idiota y necesito gafas, lo siento ;-( – zerkms

Respuesta

30

Usted debe ser capaz de crear su propia clase que deriva de AuthorizeAttribute y anular la AuthorizeCore método para proporcionar el mecanismo de autorización que desea, por lo que se puede aplicar el código de autorización personalizado utilizando un atributo en lugar de moverlo a la controlador.

Si necesita un control más preciso de la autorización, le recomiendo que cree una implementación de la interfaz IActionFilter (en un atributo, luego aplique el atributo a sus métodos). Esto le permitirá interceptar llamadas antes de que vayan al controlador, y proporcionar acciones alternativas antes de se llama al método de su controlador.

Esto se consigue implementando OnActionExecuting method en la interfaz IActionFilter. Si su lógica determina que no debe realizar la llamada al controlador en absoluto, y desea proporcionar un ActionResult para ser procesado en su lugar, entonces establecería el Result property en la instancia ActionExecutingContext pasada al método. Al hacer esto, se procesa ActionResult en lugar de ir al método del controlador para obtener un ActionResult.

Si desea devolver un código de error 403, entonces no puede usar la clase ContentResult.Usted tendrá que crear su propia clase que deriva de ActionResult y reemplazar el método ExecuteResult para establecer el StatusCode property en el HttpResponseBase a 403, de este modo:

internal class Http403Result : ActionResult 
{ 
    public override void ExecuteResult(ControllerContext context) 
    { 
     // Set the response code to 403. 
     context.HttpContext.Response.StatusCode = 403; 
    } 
} 

public class CustomActionFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     filterContext.Result = new Http403Result(); 
    } 
} 

Por supuesto, se puede generalizar la clase Http403Result tomar un constructor que aceptará el código de estado que desea devolver, pero el concepto sigue siendo el mismo.

+0

Casi lo que necesito, pero AuthorizeCore devuelve booleano, lo que significa si el usuario tiene o no acceso a la acción. La implementación predeterminada contiene redirección, es twivia, pero necesito reemplazar la salida completa. – zerkms

+0

@zerkms: respuesta actualizada para darle más información sobre cómo reemplazar la salida. – casperOne

+0

@casperOne: ¿esto funciona bien con activado en su Web.config? Tengo un escenario ligeramente diferente basado en su solución (me estoy derivando de AuthorizeAttribute en lugar de ActionFilterAttribute) y cuando devuelvo 403 no obtengo una buena página que está configurada en mis en Web.config; en su lugar obtengo una fea pantalla IE. –

46

Lo que yo haría es subclase AuthorizeAttribute y anular su HandleUnauthorizedRequest a devolver el código de estado HTTP 403 si el usuario es autenticado. Luego agregaría una sección system.webServer \ httpErrors a mi Web.Config para reemplazar el 403 predeterminado con mi página personalizada (esta última parte requiere IIS 7+). Así es como:

public class MyAuthorizeAttribute : AuthorizeAttribute { 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { 
     if (filterContext.HttpContext.User.Identity.IsAuthenticated) 
      filterContext.Result = new HttpStatusCodeResult(403); 
     else 
      filterContext.Result = new HttpUnauthorizedResult(); 
    } 
} 

<configuration> 
    <system.webServer> 
    <httpErrors errorMode="Custom" existingResponse="Replace"> 
     <remove statusCode="403" /> 
     <error statusCode="403" responseMode="ExecuteURL" path="/Error/MyCustom403page" /> 
    </httpErrors> 
    </system.webServer> 
</configuration> 
+0

Será mejor que haga una nueva pregunta ;-) – zerkms

+0

Junto con el Código de estado, también se establece la Descripción del estado. ¿Cómo obtener esta descripción de estado en el error personalizado 403 página/vista? – Vishal

Cuestiones relacionadas