Zeitlimitüberschreitung bei Ajax-Anrufen

Ich mache einen Ajax-Aufruf mit jquery zu einer asp.net mvc Controller-Aktion:

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

Wenn die Sitzung abläuft, schlägt dieser Aufruf fehl, da das Benutzerobjekt in der Sitzung gespeichert wird. Ich habe ein benutzerdefiniertes authorize-Attribut erstellt, um zu überprüfen, ob die Sitzung verloren gegangen ist, und um auf die Anmeldeseite umzuleiten. Dies funktioniert gut für Seitenanforderungen, funktioniert jedoch nicht für Ajax-Anfragen, da Sie von einer Ajax-Anfrage nicht redirect können:

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

Ich lese in einem anderen Thread, dass, wenn der Benutzer nicht authentifiziert ist und Sie eine Ajax-Anfrage machen, sollten Sie den Statuscode auf 401 (nicht autorisiert) setzen und dann in js darauf prüfen und sie auf die Login-Seite redirect. Allerdings kann ich das nicht funktionieren:

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

Im Grunde wird es auf 401 gesetzt, aber dann fährt es mit der Controller-Aktion fort und wirft ein Objekt ref, das nicht auf eine Instanz eines Objekterrorss gesetzt ist, was den Fehler 500 zurück an die clientseitige js zurückgibt. Wenn ich mein benutzerdefiniertes Autorisierungsattribut ändere, um auch AJAX-Anfragen zu validieren, und für die, die nicht authentifiziert sind, den Wert false zurückließe, würde die AJAX-Anfrage meine Anmeldeseite zurückgeben, was offensichtlich nicht funktioniert.

Wie bekomme ich das zum Laufen?

Sie könnten ein benutzerdefiniertes [Authorize] -Attribut schreiben, das JSON zurückgibt, anstatt eine 401-Ausnahme im Falle eines unautorisierten Zugriffs auszulösen, die Clientskripten erlauben würde, das Szenario ordnungsgemäß zu behandeln:

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

dann dekoriere deinen Controller / Aktionen damit und auf dem Client:

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

Ich würde JsonRequestBehavior nicht in AllowGet ändern. Stattdessen schlage ich vor:

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

und füge global js ajax errors handler hinzu:

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

Auch wenn dies bereits beantwortet ist, denke ich, dass dies die kürzeste und süßeste Antwort ist, wenn Sie .NET 4.5 verwenden. Wenig Eigenschaft namens SuppressFormsAuthenticationRedirect, die hinzugefügt wurde. Auf true gesetzt und die 302 Redirect to login Seite wird nicht ausgeführt.

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

Angenommen, Sie planen die Behandlung des Ajax-Request-Fail / Error-Callbacks, in dem Sie einen 401 Unauthorized erhalten.

Ich hatte ein ähnliches Problem und habe das gefunden

Senden Sie anstelle von JSON, unmittelbar bevor die Antwort gesendet wird, ASP.NET, um einen 401-Code zurückzugeben. 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; } } 

Dann können Sie den Kunden in JavaScript / jQuery oder was auch immer Sie verwenden, damit befassen

Fügen Sie auf der Masterseite dieses jquery-Skript hinzu ————

  

Fügen Sie in Ihrem Projekt eine cs-Datei mit dem Namen TraceFilter hinzu und schreiben Sie eine vererbte TraceFilterAttribute-class in ActionFilterAttribute. Fügen Sie die TraceFilterAttribute-class in FilterConfig.cs hinzu, die im Ordner App_Start Ihres Projekts verfügbar ist, indem Sie unter Zeile schreiben.

filters.Add (neues TraceFilterAttribute ());

Überschreiben Sie die Methode OnActionExecuting () in der TraceFilterAttribute-class. Dies überprüft automatisch die Sitzung und wenn die Sitzung null findet, ruft sie das Skript auf, das auf der Masterseite verfügbar ist, und von dort aus können Sie zu Ihrer Auswahlseite gehen.

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

Hier ist, wie ich dies in meiner benutzerdefinierten Autorisierung auf so einfache Weise handhabe, ich überprüfe, ob Sitzung aus ist und handle als unautorisiert mit einem Boolean, um zu überprüfen, ob es wirklich authentifiziert aber nicht autorisiert ist (um auf nicht autorisierte Seite umzuleiten) oder es wird nicht authentifiziert aufgrund von Sitzungszeitlimit (Weiterleitung zum Login)

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

Hoffe, wenn das jemanden führt und bitte, wenn es Kommentare gibt, ist es zu schätzen, sie zu kennen.

Vielleicht möchten Sie versuchen, HttpException zu casting und es in Ihrem Javascript zu fangen.

 throw new HttpException(401, "Auth Failed") 

Bei einem Ajax-Anruf, wenn die Sitzung abgelaufen ist, geben Sie so etwas zurück