4

我有一个 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 对象?好吧,无论如何,值得一试。

4

1 回答 1

0

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

我在我的设备上创建了一个返回“true”或“false”的 JSON 响应的Auth方法AccountController

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

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

于 2013-05-02T16:13:58.440 回答