为了账号安全,请及时绑定邮箱和手机立即绑定

处理ajax调用中的会话超时

处理ajax调用中的会话超时

哆啦的时光机 2019-10-16 13:03:44
我正在使用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请求返回我的登录页面,这显然不起作用。我该如何工作?
查看完整描述

3 回答

?
PIPIONE

TA贡献1829条经验 获得超9个赞

您可以编写一个自定义[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

    }

});


查看完整回答
反对 回复 2019-10-16
?
湖上湖

TA贡献2003条经验 获得超2个赞

我不会将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(); 

        }

   }


查看完整回答
反对 回复 2019-10-16
  • 3 回答
  • 0 关注
  • 572 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信