管理Ajax会话超时

时间:2013-04-08 19:13:30

标签: asp.net-mvc

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

目前,如果上下文报告当前请求isAuthenticated,我的代码会强制在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重定向到Login页面),

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

不幸的是,它似乎没有这样的方式。相反的是会话开始“注销”,然后执行[授权]修饰的操作方法(由于依赖于丢失的会话而失败)。

令人困惑的是,如果我然后对同一个Ajax操作进行SECOND调用(不等待新会话的超时),则第二个调用被“HandleUnauthorizedRequest”方法拦截,然后一切正常,因为我预期第一个一个(好吧,并非每一个,ajaxSuccess全局处理程序都无法接收第二个调用,即使在捕获第一个调用之后,但在解决主要问题后需要担心这一点。)

此外,即使没有ajax也可以看到相同的行为。注销会触发,但我已经预先授权了,所以无论如何都会触发此行动。

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

编辑1

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

1 个答案:

答案 0 :(得分:0)

我对此的看法与你的有点不同。以下是我的解决方案的工作原理:

我在Auth上创建了一个AccountController方法,该方法返回“true”或“false”的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);
});

<强> EDIT1

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

windows.location.reload()

而不是

windows.location.href = redirectUrl;

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