【发布时间】:2012-05-18 08:17:46
【问题描述】:
我有一个 asp.net 站点,我需要在会话超时(比如说 10 分钟)时发生弹出/层/警报。弹出窗口会说您的帐户会话将由于不活动而过期,并有一个继续会话按钮或一个注销按钮。
我在网上看到了不同的方法,但最好/正确的方法是什么?如果弹出窗口打开的时间过长,我是否必须设置额外的超时时间?
【问题讨论】:
标签: c# asp.net .net session iis
我有一个 asp.net 站点,我需要在会话超时(比如说 10 分钟)时发生弹出/层/警报。弹出窗口会说您的帐户会话将由于不活动而过期,并有一个继续会话按钮或一个注销按钮。
我在网上看到了不同的方法,但最好/正确的方法是什么?如果弹出窗口打开的时间过长,我是否必须设置额外的超时时间?
【问题讨论】:
标签: c# asp.net .net session iis
<script type="text/javascript">
var sessionTimeoutWarning = "<%= System.Configuration.ConfigurationManager.AppSettings["SessionWarning"].ToString()%>";
var sessionTimeout = "<%= Session.Timeout %>";
var sTimeout = parseInt(sessionTimeoutWarning) * 60 * 1000;
setTimeout('SessionWarning()', sTimeout);
function SessionWarning() {
var message = "Your session will expire in another " +
(parseInt(sessionTimeout) - parseInt(sessionTimeoutWarning)) +
" mins! Please Save the data before the session expires";
alert(message);
}
</script>
【讨论】:
<sessionState mode="StateServer" cookieless="false" timeout="180"></sessionState>。如何分配var sessionTimeoutWarnin?
您可以做的是使用一些 javascript 来触发消息。使用计时器在一段时间后触发(在您的应用程序中为会话超时设置的时间段 - 几分钟)。
在那段时间之后,向用户显示会话将超时的确认对话框。如果用户点击保持会话。在页面中进行虚拟回发,以免会话丢失。您还可以进行 AJAX 调用,这样用户就不会看到页面重新加载并丢失输入数据。
【讨论】:
我去看了Pranay Rana的post的文章,总体思路我喜欢,但是代码可以使用一些精简。所以这是我的版本。对于平板电脑/移动设备问题,请参见下文:
<script language="javascript" type="text/javascript">
var minutesForWarning = 4;
var sessionTimeout = parseInt("@Session.Timeout"); // razor syntax, otherwise use <%= Session.Timeout %>
var showWarning = true;
function SessionWarning() {
showWarning = false;
alert("Your session will expire in " + minutesForWarning + " mins! Please refresh page to continue working.");
// leave a second for redirection fct to be called if expired in the meantime
setTimeout(function () { showWarning = true; }, 1000);
}
function RedirectToWelcomePage() {
if (showWarning)
alert("Session expired. You will be redirected to welcome page.");
document.getElementById('logoutForm').submit();
// window.location = "../Welcome.aspx"; // alternatively use window.location to change page
}
setTimeout('SessionWarning()', (sessionTimeout - minutesForWarning) * 60 * 1000);
setTimeout('RedirectToWelcomePage()', sessionTimeout * 60 * 1000);
</script>
好吧,在平板电脑或手机上,您不能指望 setTimeout,因为当设备被锁定或浏览器处于非活动状态时,javascript 执行会暂停。相反,我正在做定期检查(在我的情况下,我认为每 10 秒就足够了):
<script language="javascript" type="text/javascript">
function addMinutes(date, minutes) {
return new Date(date.getTime() + minutes * 60 * 1000);
}
function remainingMinutes(date) {
return Math.round((date - (new Date()).getTime()) / 60 / 1000);
}
var minutesForWarning = 5;
var sessionTimeout = parseInt("@Session.Timeout");
var showWarning = true;
var showRedirect = true;
var timeToWarn = addMinutes(new Date(), sessionTimeout - minutesForWarning);
var timeToEnd = addMinutes(new Date(), sessionTimeout);
function CheckTime() {
if (showWarning && new Date() > timeToWarn && new Date() < timeToEnd) {
showRedirect = false;
showWarning = false;
alert("Your session will expire in " + remainingMinutes(timeToEnd)) + " mins! Please refresh page to continue working.");
}
if (new Date() > timeToEnd) {
if (showRedirect)
alert("Session expired. You will be redirected to welcome page ");
document.getElementById('logoutForm').submit();
// window.location = "../Welcome.aspx"; // alternatively use window.location to change page
}
if (showRedirect == false)
showRedirect = true;
}
setInterval(CheckTime, 10000);
</script>
【讨论】:
下面是一些带有 jQuery 的 JavaScript,用于警告用户 ASP.NET 表单身份验证超时,如果达到超时,会将用户重定向到登录页面。它也可以改进并适应会话超时。每当用户通过单击、键入或调整大小与页面交互时,它还将通过“ping”服务器来重置身份验证超时。
请注意,这确实会通过每次点击、按键、调整大小时 ping 来增加服务器的负载,但它非常小。不过,如果您有很多用户正在打字,您将需要评估影响。我想不出另一种方法来做到这一点,因为必须涉及服务器,因为那是超时到期的地方。
还要注意,超时在 JS 中不是硬编码的。它从服务器获取超时,因此您只需在 Web.config 中的一处维护它。
(function ($, undefined) {
if (!window.session) {
window.session = {
monitorAuthenticationTimeout: function (redirectUrl, pingUrl, warningDuration, cushion) {
// If params not specified, use defaults.
redirectUrl = redirectUrl || "~/Account/Login";
pingUrl = pingUrl || "~/Account/Ping";
warningDuration = warningDuration || 45000;
cushion = cushion || 4000;
var timeoutStartTime,
timeout,
timer,
popup,
countdown,
pinging;
var updateCountDown = function () {
var secondsRemaining = Math.floor((timeout - ((new Date()).getTime() - timeoutStartTime)) / 1000),
min = Math.floor(secondsRemaining / 60),
sec = secondsRemaining % 60;
countdown.text((min > 0 ? min + ":" : "") + (sec < 10 ? "0" + sec : sec));
// If timeout hasn't expired, continue countdown.
if (secondsRemaining > 0) {
timer = window.setTimeout(updateCountDown, 1000);
}
// Else redirect to login.
else {
window.location = redirectUrl;
}
};
var showWarning = function () {
if (!popup) {
popup = $(
"<div style=\"text-align:center; padding:2em; color: black; font-color: black; background-color:white; border:2px solid red; position:absolute; left: 50%; top:50%; width:300px; height:120px; margin-left:-150px; margin-top:-90px\">" +
"<span style=\"font-size:1.4em; font-weight:bold;\">INACTIVITY ALERT!</span><br/><br/>" +
"You will be automatically logged off.<br/><br/>" +
"<span style=\"font-size:1.4em; font-weight:bold;\" id=\"countDown\"></span><br/><br/>" +
"Click anywhere on the page to continue working." +
"</div>")
.appendTo($("body"));
countdown = popup.find("#countDown");
}
popup.show();
updateCountDown();
};
var resetTimeout = function () {
// Reset timeout by "pinging" server.
if (!pinging) {
pinging = true;
var pingTime = (new Date()).getTime();
$.ajax({
type: "GET",
dataType: "json",
url: pingUrl,
}).success(function (result) {
// Stop countdown.
window.clearTimeout(timer);
if (popup) {
popup.hide();
}
// Subract time it took to do the ping from
// the returned timeout and a little bit of
// cushion so that client will be logged out
// just before timeout has expired.
timeoutStartTime = (new Date()).getTime();
timeout = result.timeout - (timeoutStartTime - pingTime) - cushion;
// Start warning timer.
timer = window.setTimeout(showWarning, timeout - warningDuration);
pinging = false;
});
}
};
// If user interacts with browser, reset timeout.
$(document).on("mousedown mouseup keydown keyup", "", resetTimeout);
$(window).resize(resetTimeout);
// Start fresh by reseting timeout.
resetTimeout();
},
};
}
})(jQuery);
在页面加载时只需调用一次以上代码:
window.session.monitorAuthenticationTimeout(
"/Account/Login", // You could also use "@FormsAuthentication.LoginUrl" in Razor.
"/Account/Ping");
在服务器上,您需要一个返回剩余时间的操作。您也可以添加更多信息。
public JsonResult Ping()
{
return Json(new {
timeout = FormsAuthentication.Timeout.TotalMilliseconds
},
JsonRequestBehavior.AllowGet);
}
【讨论】:
如果使用滑动过期,您可以使用 jquery 和 setinterval 函数在后台执行 Ajax 发布以刷新超时,或者通过记录会话开始时间并减去过期时间来获取剩余时间的值。
【讨论】:
您必须在此处使用客户端技术 (javascript)。例如,您将使用 javascript 超时工具,然后显示警告。如果用户单击确定,您可能需要做一些事情来保持会话处于活动状态。我建议使用 jquery.ajax 方法,并调用服务器,可以是一个虚拟调用 - 只是为了保持会话活动。
【讨论】:
这个问题之前已经解决过,例如 ASP.NET - Javascript timeOut Warning based on sessionState timeOut in web.config
但是,AFAIK 没有完全可靠的方法来做到这一点,因为:
【讨论】: