处理ajax调用中的会话超时

我正在使用jquery对asp.net mvc控制器动作进行ajax调用:


[AcceptVerbs(HttpVerbs.Post)]

        public ActionResult GetWeek(string startDay)

        {

            var daysOfWeek = CompanyUtility.GetWeek(User.Company.Id, startDay);

            return Json(daysOfWeek);

        }

会话超时时,此调用将失败,因为User对象存储在会话中。我创建了一个自定义授权属性,以检查会话是否丢失并重定向到登录页面。这适用于页面请求,但不适用于ajax请求,因为您无法从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;

        }

    }

我在另一个线程上读到,当用户未通过身份验证并发出ajax请求时,应将状态代码设置为401(未授权),然后在js中进行检查并将其重定向到登录页面。但是,我无法正常工作:


protected override void OnActionExecuting(ActionExecutingContext filterContext)

        {

            if (Request.IsAjaxRequest() && (!Request.IsAuthenticated || User == null))

            {

                filterContext.RequestContext.HttpContext.Response.StatusCode = 401;

            }

            else

            {

                base.OnActionExecuting(filterContext);

            }

        }

基本上,它将其设置为401,但随后它将继续执行控制器操作,并将未设置为对象错误实例的对象ref抛出,然后将错误500返回给客户端js。如果我更改自定义的Authorize属性以同样验证ajax请求,并为未经身份验证的请求返回false,则使ajax请求返回我的登录页面,这显然不起作用。


我该如何工作?


哆啦的时光机
浏览 600回答 3
3回答

PIPIONE

您可以编写一个自定义[Authorize]属性,该属性将返回JSON,而不是在未经授权访问的情况下抛出401异常,这将允许客户端脚本优雅地处理场景:[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);        }    }}然后用它以及在客户端上装饰您的控制器/动作:$.get('@Url.Action("SomeAction")', function (result) {    if (result.message) {        alert(result.message);    } else {        // do whatever you were doing before with the results    }});

湖上湖

我不会将JsonRequestBehavior更改为AllowGet。相反,我建议:[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();            }        }    }}并添加全局js ajax错误处理程序:   $(document).ajaxError(function (xhr, props) {        if (props.status === 401) {            location.reload();         }   }
打开App,查看更多内容
随时随地看视频慕课网APP