EDIT:
he escrito anteriormente respuesta hace mucho tiempo y ahora creo que el envío de 403 no es forma correcta de ir. 403 tiene un significado ligeramente diferente y simplemente no debe usarse. Esto se corrige atributo mediante 401. Sólo difiere con context.HttpContext.Response.End()
adicional en Http401Result y diferente código HTTP:
public class OptionalAuthorizeAttribute : AuthorizeAttribute
{
private class Http401Result : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
// Set the response code to 401.
context.HttpContext.Response.StatusCode = 401;
context.HttpContext.Response.Write(CTRes.AuthorizationLostPleaseLogOutAndLogInAgainToContinue);
context.HttpContext.Response.End();
}
}
private readonly bool _authorize;
public OptionalAuthorizeAttribute()
{
_authorize = true;
}
//OptionalAuthorize is turned on on base controller class, so it has to be turned off on some controller.
//That is why parameter is introduced.
public OptionalAuthorizeAttribute(bool authorize)
{
_authorize = authorize;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//When authorize parameter is set to false, not authorization should be performed.
if (!_authorize)
return true;
var result = base.AuthorizeCore(httpContext);
return result;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
{
//Ajax request doesn't return to login page, it just returns 401 error.
filterContext.Result = new Http401Result();
}
else
base.HandleUnauthorizedRequest(filterContext);
}
}
vieja respuesta:
Aunque me gusta las ideas publicadas en otras respuestas (que tenía una idea sobre antes), necesitaba ejemplos de código. Aquí están:
Modificado atributo Autorizar:
public class OptionalAuthorizeAttribute : AuthorizeAttribute
{
private class Http403Result : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
// Set the response code to 403.
context.HttpContext.Response.StatusCode = 403;
context.HttpContext.Response.Write(CTRes.AuthorizationLostPleaseLogOutAndLogInAgainToContinue);
}
}
private readonly bool _authorize;
public OptionalAuthorizeAttribute()
{
_authorize = true;
}
//OptionalAuthorize is turned on on base controller class, so it has to be turned off on some controller.
//That is why parameter is introduced.
public OptionalAuthorizeAttribute(bool authorize)
{
_authorize = authorize;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//When authorize parameter is set to false, not authorization should be performed.
if (!_authorize)
return true;
var result = base.AuthorizeCore(httpContext);
return result;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
{
//Ajax request doesn't return to login page, it just returns 403 error.
filterContext.Result = new Http403Result();
}
else
base.HandleUnauthorizedRequest(filterContext);
}
}
HandleUnauthorizedRequest
se anula por lo que vuelve Http403Result
cuando se utiliza Ajax. Http403Result
cambia StatusCode a 403 y devuelve un mensaje al usuario en respuesta. Hay alguna lógica adicional en el atributo (parámetro authorize
), porque enciendo [Authorize]
en el controlador base y lo deshabilito en algunas páginas.
La otra parte importante es el manejo global de esta respuesta en el lado del cliente. Esto es lo que he puesto en Site.Master:
<script type="text/javascript">
$(document).ready(
function() {
$("body").ajaxError(
function(e,request) {
if (request.status == 403) {
alert(request.responseText);
window.location = '/Logout';
}
}
);
}
);
</script>
me coloque un controlador de error de Ajax global y cuando cada vez $.post
falla con un error 403, el mensaje de respuesta es alertado y se redirige al usuario a cerrar la sesión página. Ahora no tengo que manejar el error en cada solicitud $.post
, ya que se maneja de forma global.
¿Por qué 403, y no 401? 401 es manejado internamente por MVC framework (es por eso que la redirección a la página de inicio de sesión se realiza después de la autorización fallida).
¿Qué opina sobre eso?
¿Su sesión se agotó después de 20 minutos de inactividad? ¿Tu aplicación redirige a otra página? – Raja
@Raja: el estado de inicio de sesión se agota después de un tiempo y estoy preguntando cómo manejar esta situación :) Sí, redirige a la página de inicio de sesión. – LukLed