tipo por parámetros net mvc lista enviar asp asp.net-mvc asp.net-mvc-3 jquery authorize-attribute

asp.net-mvc - por - jquery ajax mvc controller



Manejo del tiempo de espera de la sesión en llamadas ajax (8)

Estoy haciendo una llamada ajax usando jquery a una acción del controlador asp.net mvc:

[AcceptVerbs(HttpVerbs.Post)] public ActionResult GetWeek(string startDay) { var daysOfWeek = CompanyUtility.GetWeek(User.Company.Id, startDay); return Json(daysOfWeek); }

Cuando la sesión expira, esta llamada fallará, ya que el objeto Usuario se almacena en la sesión. Creé un atributo de autorización personalizado para verificar si la sesión se perdió y redireccionar a la página de inicio de sesión. Esto funciona bien para las solicitudes de página, sin embargo, no funciona para las solicitudes ajax, ya que no puede redirigir desde una solicitud ajax:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class AuthorizeUserAttribute : AuthorizeAttribute { protected override bool AuthorizeCore(HttpContextBase httpContext) { if (!httpContext.Request.IsAjaxRequest()) {//validate http request. if (!httpContext.Request.IsAuthenticated || httpContext.Session["User"] == null) { FormsAuthentication.SignOut(); httpContext.Response.Redirect("~/?returnurl=" + httpContext.Request.Url.ToString()); return false; } } return true; } }

Leí en otro hilo que cuando el usuario no está autenticado y usted hace una solicitud de Ajax, debe establecer el código de estado en 401 (no autorizado) y luego verificar eso en js y redirigirlos a la página de inicio de sesión. Sin embargo, no puedo hacer que esto funcione:

protected override void OnActionExecuting(ActionExecutingContext filterContext) { if (Request.IsAjaxRequest() && (!Request.IsAuthenticated || User == null)) { filterContext.RequestContext.HttpContext.Response.StatusCode = 401; } else { base.OnActionExecuting(filterContext); } }

Básicamente, lo establecerá en 401, pero luego continuará en la acción del controlador y arrojará una referencia de objeto no configurada a una instancia de un error de objeto, que luego devuelve el error 500 a la js del lado del cliente. Si cambio mi atributo Autorizar personalizado para validar también solicitudes ajax y devuelvo falso para aquellas que no están autenticadas, eso hace que la solicitud ajax devuelva mi página de inicio de sesión, lo que obviamente no funciona.

¿Cómo hago que esto funcione?


A pesar de que esto está bien pasado respondió, creo que esta es la respuesta más corta y más dulce si está utilizando .NET 4.5. Pequeña propiedad llamada SuppressFormsAuthenticationRedirect que se agregó. Establezca en verdadero y no realizará la redirección 302 a la página de inicio de sesión.

http://msdn.microsoft.com/en-us/library/system.web.httpresponse.suppressformsauthenticationredirect.aspx

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class AjaxAuthorizeAttribute : AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { // returns a 401 already base.HandleUnauthorizedRequest(filterContext); if (filterContext.HttpContext.Request.IsAjaxRequest()) { // we simply have to tell mvc not to redirect to login page filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true; } } }

Suponiendo que planee manejar las solicitudes ajax, devuelva el error / devolución de llamada, en el que obtendrá un 401 no autorizado.


En la página maestra agregue este script jquery ------------

<script type="text/javascript"> $.ajaxSetup({ statusCode: { 403: function () { window.location.reload(); } } }); OR $.ajaxSetup({ error: function (x, e) { if (x.status == 403) { window.location.reload(); } } }); </script>

Agregue un archivo cs llamado con TraceFilter en su proyecto y escriba una clase seald TraceFilterAttribute heredando a ActionFilterAttribute. Agregue la clase TraceFilterAttribute en FilterConfig.cs disponible en la carpeta App_Start de su proyecto escribiendo debajo de la línea.

filters.Add (nuevo TraceFilterAttribute ());

Reemplazar el método OnActionExecuting () en la clase TraceFilterAttribute. Esto verificará automáticamente la sesión y si encuentra que la sesión es nula, llama al script disponible en la página maestra y desde allí puede ir a la página de su elección.

[AttributeUsage(AttributeTargets.All)] public sealed class TraceFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext != null) { HttpSessionStateBase objHttpSessionStateBase = filterContext.HttpContext.Session; var userSession = objHttpSessionStateBase["etenetID"]; if (((userSession == null) && (!objHttpSessionStateBase.IsNewSession)) || (objHttpSessionStateBase.IsNewSession)) { objHttpSessionStateBase.RemoveAll(); objHttpSessionStateBase.Clear(); objHttpSessionStateBase.Abandon(); if (filterContext.HttpContext.Request.IsAjaxRequest()) { filterContext.HttpContext.Response.StatusCode = 403; filterContext.Result = new JsonResult { Data = "LogOut" }; } else { filterContext.Result = new RedirectResult("~/Admin/GoToLogin"); } } } } }


Es posible que desee intentar lanzar HttpException y atraparlo en su javascript.

throw new HttpException(401, "Auth Failed")


Estaba teniendo un problema similar y encontré this

En lugar de devolver cualquier JSON, justo antes de enviar la respuesta, fuerce a ASP.NET a devolver un código 401. En Global.asax :

protected void Application_EndRequest() { var context = new HttpContextWrapper(Context); if (context.Request.IsAjaxRequest() && context.Response.StatusCode == 302) { Context.Response.Clear(); Context.Response.Write("**custom error message**"); Context.Response.StatusCode = 401; } }

Luego, puede dejar que el cliente se encargue de ello en JavaScript / jQuery o lo que sea que esté utilizando


No cambiaría JsonRequestBehavior a AllowGet. En cambio, sugiero:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public sealed class MyAuthorizeAttribute : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); OnAuthorizationHelp(filterContext); } internal void OnAuthorizationHelp(AuthorizationContext filterContext) { if (filterContext.Result is HttpUnauthorizedResult) { if (filterContext.HttpContext.Request.IsAjaxRequest()) { filterContext.HttpContext.Response.StatusCode = 401; filterContext.HttpContext.Response.End(); } } } }

y agregue el controlador de errores js ajax global:

$(document).ajaxError(function (xhr, props) { if (props.status === 401) { location.reload(); } }


Podría escribir un atributo personalizado [Authorize] que devuelva JSON en lugar de arrojar una excepción 401 en caso de acceso no autorizado que permita a las secuencias de comandos del cliente manejar el escenario correctamente:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class MyAuthorizeAttribute : AuthorizeAttribute { protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext.HttpContext.Request.IsAjaxRequest()) { filterContext.Result = new JsonResult { Data = new { // put whatever data you want which will be sent // to the client message = "sorry, but you were logged out" }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } else { base.HandleUnauthorizedRequest(filterContext); } } }

luego decora tu controlador / acciones con él y con el cliente:

$.get(''@Url.Action("SomeAction")'', function (result) { if (result.message) { alert(result.message); } else { // do whatever you were doing before with the results } });


así es como manejo esto de una manera tan simple en mi autorización personalizada, compruebo si la sesión está cerrada y manejo esto como no autorizado con un booleano para verificar si está realmente autenticado pero no autorizado (para redireccionar a una página no autorizada) o no está autenticado debido al tiempo de espera de la sesión (redirigir a Iniciar sesión)

private bool ispha_LoggedIn = false; protected override bool AuthorizeCore(HttpContextBase httpContext) { ispha_LoggedIn = false; var session = httpContext.Session; bool authorize = false; if (httpContext.Session["authenticationInfo"] == null) { return authorize; } using (OrchtechHR_MVCEntities db = new OrchtechHR_MVCEntities()) { UserAuthenticationController UM = new UserAuthenticationController(); foreach (var roles in userAssignedRoles) { authorize = UM.IsUserInRole(httpContext.User.Identity.Name, roles); if (authorize) { return authorize; } } } ispha_LoggedIn = true; return authorize; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (ispha_LoggedIn==false) { filterContext.Result = new RedirectResult("~/UserAuthentication/LogIn"); } else { filterContext.Result = new RedirectResult("~/Dashboard/UnAuthorized"); } }

Espero que si esto guía a alguien y por favor si hay comentarios, se agradece que los conozca.


en la llamada ajax si la sesión expiró devolver algo como esto

<script> $(function(){ location.reload(); }); </script>

jaja...