Session timeout handling in ajax calls

I am making an ajax call using jquery for an asp.net mvc controller action:

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

When the session time ends, this call will not be completed because the user object will be saved in the session. I created a special authorization attribute to check if the session was lost and redirected to the login page. This works fine for page requests, however it does not work for ajax requests, since you cannot redirect an ajax request:

 [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; } } 

I read in another thread that when the user is not authenticated and you make an ajax request, you must set the status code to 401 (unauthorized) and then check it in js and redirect to the login page. However, I cannot get this to work:

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

Basically, he will set it to 401, but then he will continue the action of the controller and throw away the ref object not set in the object error instance, which then returns the 500 error back to the client side js, If I change my own Authorize attribute to check ajax- requests, and also return false for those that did not authenticate, this makes the ajax request return my login page, which obviously does not work.

How do I make this work?

+51
jquery asp.net-mvc asp.net-mvc-3
Mar 08 2018-11-11T00:
source share
8 answers

You can write your own [Authorize] attribute, which will return JSON instead of throwing 401 exception in case of unauthorized access, which will allow client scripts to process the script gracefully:

 [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); } } } 

then decorate your controller / actions with it and on the client:

 $.get('@Url.Action("SomeAction")', function (result) { if (result.message) { alert(result.message); } else { // do whatever you were doing before with the results } }); 
+81
Mar 09 2018-11-11T00:
source share

I would not change JsonRequestBehavior to AllowGet. Instead, I suggest:

 [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(); } } } } 

and add the global js ajax error handler:

  $(document).ajaxError(function (xhr, props) { if (props.status === 401) { location.reload(); } } 
+36
Jun 02 2018-12-12T00:
source share

Even if this went well, I think this is the shortest and sweetest answer if you are using .NET 4.5. A small property called SuppressFormsAuthenticationRedirect that has been added. Set it to True and it will not redirect 302 to the login page.

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; } } } 

Assuming you plan to handle an ajax error / error callback in which you will get an unauthorized 401.

+8
May 11 '13 at 2:22
source share

I had a similar problem and I found this

Instead of returning any JSON before sending a response, force ASP.NET to return the 401 code. In 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; } } 

Then you can let the client handle this in JavaScript / jQuery or whatever you use

+4
Dec 15 '12 at 18:37
source share

On the main page add this jquery script ------------

 <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> 

Add a cs file named TraceFilter to your project and write the printd class TraceFilterAttribute that inherits ActionFilterAttribute. Add the TraceFilterAttribute class to FilterConfig.cs, available in the App_Start folder of your project, by writing the line below.

filters.Add (new TraceFilterAttribute ());

Override the OnActionExecuting () method in the TraceFilterAttribute class. This will automatically check the session and, if it finds a zero session, it will call the script available on the main page, and with their help you can go to the selection page.

 [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"); } } } } } 
+4
Jul 01 '13 at 11:46 on
source share

here is how i handle it so simple in my user authorization, i check if the session is disconnected and treat it as unauthorized with a boolean to check if it is authenticated but not authorized (to redirect to an un-authorized page) or not authenticated due to session timeout (entry redirection)

  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"); } } 

I hope if this helps someone and please if there are comments that value him in order to get to know them.

+1
May 7 '16 at 14:55
source share

You might want to try HttpException and catch it in your javascript.

 throw new HttpException(401, "Auth Failed") 
0
Mar 08 '11 at 10:11
source share

when calling ajax, if the session has expired, return something like this

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

haha ...

-2
Mar 31 '16 at 16:07
source share



All Articles