【问题标题】:Managing Ajax Session Timed Out管理 Ajax 会话超时
【发布时间】:2013-05-03 00:21:04
【问题描述】:

我有一个 ASP.Net MVC4 应用程序,其页面包含许多 Ajax 操作。我正在尝试处理会话到期后发生的情况。

目前,如果上下文报告当前请求已通过身份验证,我的代码会强制在 Session_Start() 上运行“FormsAuthentication.SignOut()”。

protected void Session_Start(object sender, EventArgs e) {
    if (HttpContext.Current.Request.IsAuthenticated) {
        FormsAuthentication.SignOut();         // Drop all the information held in the session
        // now continue with request....
    }
}

下一部分是“HandleUnauthorizedRequest”的覆盖,它应该捕获未经授权的请求,测试它是否是 ajax 请求,如果不是则继续,否则返回特定的 JSON 以指示失败。

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
    if (filterContext.HttpContext.Request.IsAjaxRequest()) {
        filterContext.Result = new JsonResult { Data = new { ajaxUnauthorizedMessage = "sorry, but your session has expired..." }, JsonRequestBehavior = JsonRequestBehavior.AllowGet};
    } else {
        base.HandleUnauthorizedRequest(filterContext);
    }
}

最后,我有一个全局 jquery ajaxSuccess 处理程序,它测试我上面的消息,并提醒用户注意问题,然后强制重新加载(这应该导致 MVC 重定向到登录页面),

$(document).ajaxSuccess(function (result) {
    if (result.ajaxUnauthorizedMessage) {
        alert(result.ajaxUnauthorizedMessage);
        location.reload();
    }
});

不幸的是,它似乎不是那样工作的。取而代之的是会话开始“注销”,然后执行 [Authorize] 修饰的操作方法(然后由于对丢失会话的依赖而失败)。

令人困惑的是,如果我随后对同一个 Ajax 操作进行第二次调用(不等待新会话的超时),第二次调用会被“HandleUnauthorizedRequest”方法拦截,然后一切都按我预期的第一次调用一个到(嗯,不是所有的,ajaxSuccess 全局处理程序无法接第二个调用,即使在捕获第一个调用之后,但在我解决了主要问题之后,这是需要担心的事情)。

此外,即使没有 ajax,也会看到相同的行为。退出会触发,但我是“预先授权的”,因此无论如何都会触发操作。

如何成功取消授权,以便“HandleUnauthorizedRequest”在我期望的时候触发?

编辑 1

一时兴起,我编辑了 Session_Start(),并让它删除了所有请求和响应 Cookie。我惊讶地发现需要 auth 的 Action 方法仍然触发,更惊讶的是 Cookies 都回来了!他们在删除后仍然存在!我猜 Session_Start 不是在处理真正的 Request 对象?好吧,无论如何,值得一试。

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    我的处理方式与您有所不同。以下是我的解决方案的工作原理:

    我在 AccountController 上创建了一个 Auth 方法,该方法返回“真”或“假”的 JSON 响应

    [AllowAnonymous]
    [DoNotResetAuthCookie]
    [OutputCache(NoStore=true, Duration=0)]
    public JsonResult Auth()
    {
        return Json(Request.IsAuthenticated, JsonRequestBehavior.AllowGet);
    }
    

    我实现了与您实现的相同的Session_Start()

    最后,在我的 javascript 中,我会定期检查我是否仍然通过身份验证,如果没有,那么我将页面重定向如下:

    function redirectOnNotAuthorized(authUrl, redirectUrl) {
        $.get(authUrl)
             .done(function (data) {
                 var isStillAuthorized = data || false;
                 if (!isStillAuthorized) {
                     window.location.href = redirectUrl;
                 }
             })
            .fail(function () {
                window.location.href = redirectUrl;
            });
    }
    
    $(function() {
        var timer, duration;
        duration = 20000;
        window.stillAuthorized = function stillAuthorized() {
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(stillAuthorized, duration);
            redirectOnNotAuthorized("Account/Auth", "Account/LogOn");
        };
        timer = setTimeout(stillAuthorized, duration);
    });
    

    编辑1

    我学到了一些东西...在redirectOnNotAuthorized 函数中它也可以设置

    windows.location.reload()
    

    而不是

    windows.location.href = redirectUrl;
    

    从而简化代码并减少对应用的依赖。

    【讨论】:

    • 谢谢!我很快会再次讨论这个话题,我想我会试试你的方法。它看起来与我折腾的其他一些想法相似。欣赏!
    猜你喜欢
    • 1970-01-01
    • 2014-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    • 2010-12-11
    • 2013-05-17
    • 2017-04-01
    相关资源
    最近更新 更多