Jua*_*DYB 0 asp.net ajax asp.net-mvc session jquery
我在 ASP.NET MVC 中有一个 Web,我想在会话超时后自动重定向到登录页面,而无需用户干预。例如像 Gmail 那样。
现在我正在对控制器进行 ajax 调用,以 5 秒的间隔检查会话。
[HttpPost]
public JsonResult CheckSession(string currentUrl)
{
bool result = false;
Uri url = new Uri(currentUrl);
if (PublicUrl.Contains(url.AbsolutePath))
{
result = true;
}
else
{
result = HttpContext.User.Identity.IsAuthenticated;
}
return Json(result);
}
Run Code Online (Sandbox Code Playgroud)
如果结果为 false,我会在 JQuery 上进行重定向。
如果我手动删除浏览器上的 cookie,这会很有效。但问题是会话永远不会过期,因为我每 5 秒对服务器进行一次调用,因此会话超时会在每次服务器端调用时重置。
如何在会话到期时自动重定向?
这里有几个单独的问题:服务器会话超时、客户端对服务器会话超时的感知以及对用户不活动执行某些操作。
1)如何在服务器端实现会话超时?
2)由于您通过心跳(每 5 秒)保持会话活动,因此您可能永远不会在服务器上达到会话超时。
您只能在客户端进行管理,方法是在达到超时值后使用 JavaScript 进行注销调用。使用 window.setTimeout() 在客户端设置不活动超时。当计时器触发时,将浏览器重定向到注销控制器或 sessionExpired 控制器(您的选择)。使用 beforeUnload 事件清除计时器,并在页面加载时设置一个新计时器。
然后,让服务器超时值处理用户关闭浏览器、心跳停止的情况。
摘录自 web.config,将我的会话超时定义为 20 分钟:
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="20" slidingExpiration="true" protection="All" name="ilApp" requireSSL="false" defaultUrl="~/Account/Login" />
</authentication>
<sessionState timeout="20" />
Run Code Online (Sandbox Code Playgroud)
我添加到 /Shared/_Layout.cshtml 的 JavaScript 代码,因为该文件包含在我网站的每个页面中:
@* Redirect browser to session expiration page on timeout *@
@{
var authenticationSettings = System.Configuration.ConfigurationManager.GetSection("system.web/authentication") as System.Web.Configuration.AuthenticationSection;
}
<script type="text/javascript">
$(document).ready(function () {
function ilSessionTimeout() {
window.location = '@Url.Action("SessionExpired", "Account", new { area = "" })';
};
function ilSessionTimeoutWarning() {
$.jGrowl('You will be logged off soon due to inactivity.', { sticky: true, theme: 'growl-warning', header: 'Attention' });
};
// remember our timers so we can cancel when we unload this page and reset them on the next page load
var g_pageTimer = window.setTimeout(ilSessionTimeout, @authenticationSettings.Forms.Timeout.TotalMilliseconds);
var g_pageTimerWarning = window.setTimeout(ilSessionTimeoutWarning, Math.round(@authenticationSettings.Forms.Timeout.TotalMilliseconds*0.8));
// clean up anything that needs cleaning before we leave this page
window.onbeforeunload = function(e) {
// clear the timers
window.clearTimeout(g_pageTimer);
window.clearTimeout(g_pageTimerWarning);
};
});
</script>
Run Code Online (Sandbox Code Playgroud)
这会设置两个计时器,一个用于会话超时时间(基于 web.config 中定义的值),第二个计时器在 80% 到期时使用 jGrowl 显示警告消息。我在 JavaScript 全局变量 (g_pageTimer*) 中保留了卸载事件的两个计时器的句柄。
我连接到 window.onbeforeunload 以确保在页面即将更改时取消计时器。如果没有这个,无论客户端活动如何,超时都是绝对的重定向到注销。
当超时计时器触发时,我会重定向到网站上的一个页面 /Account/SessionExpired,该页面向用户显示一条消息,然后完成注销。在我的示例中,我使用的是 ASP.Net Identity 2,但无论您在注销期间通常执行什么操作,都可以在此处执行。
//
// GET: /Account/SessionExpired
[AllowAnonymous]
public ActionResult SessionExpired()
{
try
{
System.Web.HttpContext.Current.Session.RemoveAll(); // Remove all session variables that we used
AuthenticationManager.SignOut();
}
catch
{
// do nothing
}
return View();
}
Run Code Online (Sandbox Code Playgroud)