我在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);
}
如果结果为false,我会对JQuery进行重定向。
如果我手动删除浏览器上的cookie,这很有效。但问题是会话永远不会过期,因为我每隔5秒就会调用一次服务器,因此会话超时会在每次服务器端调用时重置。
如何自动重定向会话到期?
答案 0 :(得分:3)
这里有几个不同的问题:服务器会话超时,服务器会话超时的客户端感知,以及对用户不活动的某些操作。
1)如何在服务器端实现会话超时?
2)由于您使用心跳(每5秒)使会话保持活动状态,因此您可能永远不会在服务器上达到会话超时。
您只能在客户端进行管理,方法是在达到超时值后使用JavaScript进行注销调用。使用window.setTimeout()在客户端设置不活动超时。当计时器触发时,将浏览器重定向到注销控制器或sessionExpired控制器(您的选择)。使用beforeUnload事件清除计时器,并在页面加载时设置一个新计时器。
然后,让服务器超时值处理用户关闭浏览器并且心跳停止的情况。
摘自web.config,将会话超时定义为20分钟:
responseText
我添加到/Shared/_Layout.cshtml的javascript代码作为此文件包含在我网站的每个页面中:
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="20" slidingExpiration="true" protection="All" name="ilApp" requireSSL="false" defaultUrl="~/Account/Login" />
</authentication>
<sessionState timeout="20" />
这将设置两个计时器,一个用于会话超时期限(基于web.config中定义的值),另一个计时器在80%到期时使用jGrowl显示警告消息。我在javascript全局变量(g_pageTimer *)中为卸载事件保留了两个计时器的句柄。
我迷上了window.onbeforeunload,以确保在页面即将更改时取消我的计时器。如果没有这个,超时是绝对的,无论客户端活动如何,都会重定向到注销。
当超时计时器触发时,我会重定向到我的站点上的页面/ Account / SessionExpired,它向用户显示一条消息,然后完成注销。在我的例子中,我使用的是ASP.Net Identity 2,但无论你在注销时通常做什么,都可以在这里做。
@* 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>