para pagina estado códigos código codigos codes 4xx asp.net-mvc rest asp.net-mvc-2

pagina - En Asp.Net MVC 2 hay una mejor manera de devolver los códigos de estado 401 sin obtener una redirección de autenticación



http response (5)

¿Qué hay de la decoración de su controlador / acciones con un filtro personalizado:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] public class RequiresAuthenticationAttribute : FilterAttribute, IAuthorizationFilter { public void OnAuthorization(AuthorizationContext filterContext) { var user = filterContext.HttpContext.User; if (!user.Identity.IsAuthenticated) { filterContext.HttpContext.Response.StatusCode = 401; filterContext.HttpContext.Response.End(); } } }

y en tu controlador:

public class HomeController : Controller { public ActionResult Index() { return View(); } [RequiresAuthentication] public ActionResult AuthenticatedIndex() { return View(); } }

Tengo una parte de mi sitio que tiene una API REST xml / json liviana. La mayor parte de mi sitio está detrás de la autenticación de formularios, pero solo algunas de mis acciones API requieren autenticación.

Tengo un AuthorizeAttribute personalizado para mi API que utilizo para verificar ciertos permisos y cuando falla da como resultado un 401. Todo está bien, excepto porque estoy usando auth de formularios, Asp.net lo convierte convenientemente en un redireccionamiento 302 a mi página de inicio de sesión.

He visto algunas preguntas anteriores que parecen un poco hackear para devolver un 403 en su lugar o para poner algo de lógica en el vacío global.asax protected Application_EndRequest () que esencialmente convertirá 302 a 401 donde cumpla con los criterios.

Lo que estoy haciendo ahora es como una de las preguntas, pero en lugar de verificar Application_EndRequest () para un 302, hago que mi atributo authorize devuelva 666, lo que me indica que debo establecerlo en un 401.

Aquí está mi código:

protected void Application_EndRequest() { if (Context.Response.StatusCode == MyAuthAttribute.AUTHORIZATION_FAILED_STATUS) { //check for 666 - status code of hidden 401 Context.Response.StatusCode = 401; } }

Aunque esto funciona, mi pregunta es si hay algo en Asp.net MVC 2 que me impida tener que hacer esto. O, en general, ¿hay una mejor manera? Pensaría que esto le vendría mucho a cualquiera que haga api de REST o simplemente a personas que hacen solicitudes de ajax en sus controladores. Lo último que desea es hacer una solicitud y obtener el contenido de una página de inicio de sesión en lugar de json.


TurnOffTheRedirectionAtIIS

Desde MSDN, este artículo explica cómo evitar la redirección de 401 respuestas:).

Citando:

Usando el Administrador de IIS, haga clic derecho en el archivo WinLogin.aspx, haga clic en Propiedades, y luego vaya a la pestaña Errores personalizados para Editar los diversos errores 401 y asigne una redirección personalizada. Desafortunadamente, esta redirección debe ser un archivo estático, no procesará una página ASP.NET. Mi solución es redirigir a un archivo Redirect401.htm estático, con la ruta física completa, que contiene javascript, o una metaetiqueta, para redirigir al formulario de inicio de sesión ASP.NET real, llamado WebLogin.aspx. Tenga en cuenta que pierde el ReturnUrl original en estas redirecciones, ya que la redirección de errores de IIS requiere un archivo html estático sin nada dinámico, por lo que tendrá que manejar esto más adelante.

Espero que te ayude


La solución más simple y limpia que he encontrado para esto es registrar una devolución de llamada con el evento jQuery.ajaxSuccess () y verificar el encabezado de respuesta "X-AspNetMvc-Version".

Cada solicitud jQuery Ajax en mi aplicación es manejada por Mvc así que si falta el encabezado sé que mi solicitud ha sido redireccionada a la página de inicio de sesión, y simplemente recargo la página para un redireccionamiento de alto nivel:

$(document).ajaxSuccess(function(event, XMLHttpRequest, ajaxOptions) { // if request returns non MVC page reload because this means the user // session has expired var mvcHeaderName = "X-AspNetMvc-Version"; var mvcHeaderValue = XMLHttpRequest.getResponseHeader(mvcHeaderName); if (!mvcHeaderValue) { location.reload(); } });

La recarga de la página puede causar algunos errores de Javascript (dependiendo de lo que esté haciendo con la respuesta de Ajax) pero en la mayoría de los casos en que la depuración está desactivada, el usuario nunca los verá.

Si no desea utilizar el encabezado integrado, estoy seguro de que puede agregar fácilmente uno personalizado y seguir el mismo patrón.


Otra forma de hacerlo es implementar un ActionResult personalizado. En mi caso, quería uno de todos modos, ya que quería una forma simple de enviar datos con encabezados personalizados y códigos de respuesta (para una API REST). Encontré la idea de hacer un DelegatingActionResult y simplemente agregué una llamada a Response.End() . Este es el resultado:

public class DelegatingActionResult : ActionResult { public override void ExecuteResult(ControllerContext context) { if (context == null) throw new ArgumentNullException("context"); Command(context); // prevent ASP.Net from hijacking our headers context.HttpContext.Response.End(); } private readonly Action<ControllerContext> Command; public DelegatingActionResult(Action<ControllerContext> command) { if (command == null) throw new ArgumentNullException("command"); Command = command; } }


Todavía estoy usando la técnica de solicitud final, así que pensé que iba a hacer que la respuesta, pero en realidad cualquiera de las opciones que figuran aquí son en general lo que diría que son las mejores respuestas hasta ahora.

protected void Application_EndRequest() { if (Context.Response.StatusCode == MyAuthAttribute.AUTHORIZATION_FAILED_STATUS) { //check for 666 - status code of hidden 401 Context.Response.StatusCode = 401; } }