C# 保持 ASP.NET 会话打开/活动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1431733/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Keeping ASP.NET Session Open / Alive
提问by Alex
Which is the easiest and most unobstrusive way to keep an ASP.NET session alive as long as the user has the browser window open? Is it timed AJAX calls? I want to prevent the following: sometimes users keep their window open for a long time, then enter stuff, and on submit nothing works anymore because the server side session expired. I don't want to increase the timeout value for more than 10 min on the server as I want closed sessions (by closing the browser window) to time out fast.
只要用户打开浏览器窗口,保持 ASP.NET 会话活动的最简单和最不引人注目的方法是什么?是定时 AJAX 调用吗?我想防止以下情况:有时用户将他们的窗口打开很长时间,然后输入内容,并且在提交时不再起作用,因为服务器端会话已过期。我不想在服务器上增加超过 10 分钟的超时值,因为我希望关闭的会话(通过关闭浏览器窗口)快速超时。
Suggestions, code samples?
建议,代码示例?
采纳答案by veggerby
I use JQuery to perform a simple AJAX call to a dummy HTTP Handler that does nothing but keeping my Session alive:
我使用 JQuery 对一个虚拟 HTTP 处理程序执行一个简单的 AJAX 调用,该处理程序除了保持我的会话处于活动状态之外什么都不做:
function setHeartbeat() {
setTimeout("heartbeat()", 5*60*1000); // every 5 min
}
function heartbeat() {
$.get(
"/SessionHeartbeat.ashx",
null,
function(data) {
//$("#heartbeat").show().fadeOut(1000); // just a little "red flash" in the corner :)
setHeartbeat();
},
"json"
);
}
Session handler can be as simple as:
会话处理程序可以很简单:
public class SessionHeartbeatHttpHandler : IHttpHandler, IRequiresSessionState
{
public bool IsReusable { get { return false; } }
public void ProcessRequest(HttpContext context)
{
context.Session["Heartbeat"] = DateTime.Now;
}
}
The key is to add IRequiresSessionState, otherwise Session won't be available (= null). The handler can of course also return a JSON serialized object if some data should be returned to the calling JavaScript.
关键是添加IRequiresSessionState,否则Session将不可用(= null)。如果一些数据应该返回给调用 JavaScript,处理程序当然也可以返回一个 JSON 序列化对象。
Made available through web.config:
通过 web.config 提供:
<httpHandlers>
<add verb="GET,HEAD" path="SessionHeartbeat.ashx" validate="false" type="SessionHeartbeatHttpHandler"/>
</httpHandlers>
addedfrom balexandreon August 14th, 2012
2012 年 8 月 14 日从balexandre添加
I liked so much of this example, that I want to improve with the HTML/CSS and the beat part
我非常喜欢这个例子,我想用 HTML/CSS 和节拍部分来改进
change this
改变这个
//$("#heartbeat").show().fadeOut(1000); // just a little "red flash" in the corner :)
into
进入
beatHeart(2); // just a little "red flash" in the corner :)
and add
并添加
// beat the heart
// 'times' (int): nr of times to beat
function beatHeart(times) {
var interval = setInterval(function () {
$(".heartbeat").fadeIn(500, function () {
$(".heartbeat").fadeOut(500);
});
}, 1000); // beat every second
// after n times, let's clear the interval (adding 100ms of safe gap)
setTimeout(function () { clearInterval(interval); }, (1000 * times) + 100);
}
HTML and CSS
HTML 和 CSS
<div class="heartbeat">♥</div>
/* HEARBEAT */
.heartbeat {
position: absolute;
display: none;
margin: 5px;
color: red;
right: 0;
top: 0;
}
here is a live examplefor only the beating part: http://jsbin.com/ibagob/1/
这是一个仅用于殴打部分的现场示例:http: //jsbin.com/ibagob/1/
回答by Henry Troup
Do you really need to keep the session (do you have data in it?) or is it enough to fake this by reinstantiating the session when a request comes in? If the first, use the method above. If the second, try something like using the Session_End event handler.
您是否真的需要保留会话(其中有数据吗?)还是通过在请求进入时重新实例化会话来伪造这一点就足够了?如果是第一种,请使用上面的方法。如果是第二个,请尝试使用 Session_End 事件处理程序。
If you have Forms Authentication, then you get something in the Global.asax.cs like
如果你有表单身份验证,那么你会在 Global.asax.cs 中得到一些东西,比如
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(formsCookie.Value);
if (ticket.Expired)
{
Request.Cookies.Remove(FormsAuthentication.FormsCookieName);
FormsAuthentication.SignOut();
...
}
else
{ ...
// renew ticket if old
ticket = FormsAuthentication.RenewTicketIfOld(ticket);
...
}
And you set the ticket lifetime much longer than the session lifetime. If you're not authenticating, or using a different authentication method, there are similar tricks. Microsoft TFS web interface and SharePoint seem to use these - the give away is that if you click a link on a stale page, you get authentication prompts in the popup window, but if you just use a command, it works.
并且您设置的票证有效期比会话有效期长得多。如果您不进行身份验证或使用不同的身份验证方法,则有类似的技巧。Microsoft TFS Web 界面和 SharePoint 似乎使用了这些 - 如果您单击陈旧页面上的链接,您会在弹出窗口中收到身份验证提示,但如果您只使用命令,它就会起作用。
回答by Maryan
If you are using ASP.NET MVC – you do not need an additional HTTP handler and some modifications of the web.config file. All you need – just to add some simple action in a Home/Common controller:
如果您使用的是 ASP.NET MVC – 您不需要额外的 HTTP 处理程序和对 web.config 文件的一些修改。您只需要在 Home/Common 控制器中添加一些简单的操作即可:
[HttpPost]
public JsonResult KeepSessionAlive() {
return new JsonResult {Data = "Success"};
}
, write a piece of JavaScript code like this one (I have put it in one of site's JavaScript file):
,写一段这样的 JavaScript 代码(我已经把它放在站点的一个 JavaScript 文件中):
var keepSessionAlive = false;
var keepSessionAliveUrl = null;
function SetupSessionUpdater(actionUrl) {
keepSessionAliveUrl = actionUrl;
var container = $("#body");
container.mousemove(function () { keepSessionAlive = true; });
container.keydown(function () { keepSessionAlive = true; });
CheckToKeepSessionAlive();
}
function CheckToKeepSessionAlive() {
setTimeout("KeepSessionAlive()", 5*60*1000);
}
function KeepSessionAlive() {
if (keepSessionAlive && keepSessionAliveUrl != null) {
$.ajax({
type: "POST",
url: keepSessionAliveUrl,
success: function () { keepSessionAlive = false; }
});
}
CheckToKeepSessionAlive();
}
, and initialize this functionality by calling a JavaScript function:
,并通过调用 JavaScript 函数来初始化此功能:
SetupSessionUpdater('/Home/KeepSessionAlive');
Please note!I have implemented this functionality only for authorized users (there is no reason to keep session state for guests in most cases) and decision to keep session state active is not only based on – is browser open or not, but authorized user must do some activity on the site (move a mouse or type some key).
请注意!我只为授权用户实现了这个功能(在大多数情况下没有理由为来宾保持会话状态)并且决定保持会话状态活跃不仅基于 - 浏览器是否打开,而且授权用户必须做一些活动在网站上(移动鼠标或键入一些键)。
回答by BornToCode
Whenever you make a request to the server the session timeout resets. So you can just make an ajax call to an empty HTTP handler on the server, but make sure the handler's cache is disabled, otherwise the browser will cache your handler and won't make a new request.
每当您向服务器发出请求时,会话超时都会重置。因此,您可以对服务器上的空 HTTP 处理程序进行 ajax 调用,但请确保禁用处理程序的缓存,否则浏览器将缓存您的处理程序并且不会发出新请求。
KeepSessionAlive.ashx.cs
KeepSessionAlive.ashx.cs
public class KeepSessionAlive : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
context.Response.Cache.SetNoStore();
context.Response.Cache.SetNoServerCaching();
}
}
.JS:
.JS:
window.onload = function () {
setInterval("KeepSessionAlive()", 60000)
}
function KeepSessionAlive() {
url = "/KeepSessionAlive.ashx?";
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", url, true);
xmlHttp.send();
}
@veggerby - There is no need for the overhead of storing variables in the session. Just preforming a request to the server is enough.
@veggerby - 不需要在会话中存储变量的开销。只需向服务器发送请求就足够了。
回答by Peter
Here is a alternative solution that should survive if the client pc goes into sleep mode.
这是一个替代解决方案,如果客户端电脑进入睡眠模式,它应该可以生存。
If you have a huge amount of logged in users then use this cautiously as this could eat a lot of server memory.
如果您有大量登录用户,请谨慎使用它,因为这可能会占用大量服务器内存。
After you login (i do this in the LoggedIn event of the login control)
登录后(我在登录控件的 LoggedIn 事件中执行此操作)
Dim loggedOutAfterInactivity As Integer = 999 'Minutes
'Keep the session alive as long as the authentication cookie.
Session.Timeout = loggedOutAfterInactivity
'Get the authenticationTicket, decrypt and change timeout and create a new one.
Dim formsAuthenticationTicketCookie As HttpCookie = _
Response.Cookies(FormsAuthentication.FormsCookieName)
Dim ticket As FormsAuthenticationTicket = _
FormsAuthentication.Decrypt(formsAuthenticationTicketCookie.Value)
Dim newTicket As New FormsAuthenticationTicket(
ticket.Version, ticket.Name, ticket.IssueDate,
ticket.IssueDate.AddMinutes(loggedOutAfterInactivity),
ticket.IsPersistent, ticket.UserData)
formsAuthenticationTicketCookie.Value = FormsAuthentication.Encrypt(newTicket)
回答by ANKIT KISHOR
you can just write this code in you java script file thats it.
你可以在你的java脚本文件中编写这段代码,就是这样。
$(document).ready(function () {
var delay = (20-1)*60*1000;
window.setInterval(function () {
var url = 'put the url of some Dummy page';
$.get(url);
}, delay);
});
The (20-1)*60*1000
is refresh time, it will refresh the session timeout. Refresh timeout is calculated as default time out of iis = 20 minutes, means 20 × 60000 = 1200000 milliseconds - 60000 millisecond (One minutes before session expires ) is 1140000.
该(20-1)*60*1000
是刷新时间,这将刷新会话超时。刷新超时计算为 iis 中的默认时间 = 20 分钟,即 20 × 60000 = 1200000 毫秒 - 60000 毫秒(会话过期前一分钟)为 1140000。
回答by Colin
I spent a few days trying to figure out how to prolong a users session in WebForms via a popup dialog giving the user the option to renew the session or to allow it to expire. The #1 thing that you need to know is that you don't need any of this fancy 'HttpContext' stuff going on in some of the other answers. All you need is jQuery's $.post(); method. For example, while debugging I used:
我花了几天时间试图找出如何通过弹出对话框延长 WebForms 中的用户会话,让用户可以选择续订会话或允许会话过期。您需要知道的第一件事是,您不需要其他一些答案中出现的任何这种花哨的“HttpContext”内容。你所需要的只是 jQuery 的 $.post(); 方法。例如,在调试时我使用了:
$.post("http://localhost:5562/Members/Location/Default.aspx");
and on your live site you would use something like:
在您的实时站点上,您将使用以下内容:
$.post("http://mysite/Members/Location/Default.aspx");
It's as easy as that. Furthermore, if you'd like to prompt the user with the option to renew their session do something similar to the following:
就这么简单。此外,如果您想提示用户选择续订会话,请执行以下类似操作:
<script type="text/javascript">
$(function () {
var t = 9;
var prolongBool = false;
var originURL = document.location.origin;
var expireTime = <%= FormsAuthentication.Timeout.TotalMinutes %>;
// Dialog Counter
var dialogCounter = function() {
setTimeout( function() {
$('#tickVar').text(t);
t--;
if(t <= 0 && prolongBool == false) {
var originURL = document.location.origin;
window.location.replace(originURL + "/timeout.aspx");
return;
}
else if(t <= 0) {
return;
}
dialogCounter();
}, 1000);
}
var refreshDialogTimer = function() {
setTimeout(function() {
$('#timeoutDialog').dialog('open');
}, (expireTime * 1000 * 60 - (10 * 1000)) );
};
refreshDialogTimer();
$('#timeoutDialog').dialog({
title: "Session Expiring!",
autoOpen: false,
height: 170,
width: 350,
modal: true,
buttons: {
'Yes': function () {
prolongBool = true;
$.post("http://localhost:5562/Members/Location/Default.aspx");
refreshDialogTimer();
$(this).dialog("close");
},
Cancel: function () {
var originURL = document.location.origin;
window.location.replace(originURL + "/timeout.aspx");
}
},
open: function() {
prolongBool = false;
$('#tickVar').text(10);
t = 9;
dialogCounter();
}
}); // end timeoutDialog
}); //End page load
</script>
Don't forget to add the Dialog to your html:
不要忘记将 Dialog 添加到您的 html:
<div id="timeoutDialog" class='modal'>
<form>
<fieldset>
<label for="timeoutDialog">Your session will expire in</label>
<label for="timeoutDialog" id="tickVar">10</label>
<label for="timeoutDialog">seconds, would you like to renew your session?</label>
</fieldset>
</form>
</div>
回答by AlexPalla
Here JQuery plugin version of Maryan solution with handle optimization. Only with JQuery 1.7+!
这里是带有句柄优化的 Maryan 解决方案的 JQuery 插件版本。仅适用于 JQuery 1.7+!
(function ($) {
$.fn.heartbeat = function (options) {
var settings = $.extend({
// These are the defaults.
events: 'mousemove keydown'
, url: '/Home/KeepSessionAlive'
, every: 5*60*1000
}, options);
var keepSessionAlive = false
, $container = $(this)
, handler = function () {
keepSessionAlive = true;
$container.off(settings.events, handler)
}, reset = function () {
keepSessionAlive = false;
$container.on(settings.events, handler);
setTimeout(sessionAlive, settings.every);
}, sessionAlive = function () {
keepSessionAlive && $.ajax({
type: "POST"
, url: settings.url
,success: reset
});
};
reset();
return this;
}
})(jQuery)
and how it does import in your *.cshtml
以及它如何导入您的 *.cshtml
$('body').heartbeat(); // Simple
$('body').heartbeat({url:'@Url.Action("Home", "heartbeat")'}); // different url
$('body').heartbeat({every:6*60*1000}); // different timeout
回答by ShowJX1990
In regards to veggerby's solution, if you are trying to implement it on a VB app, be careful trying to run the supplied code through a translator. The following will work:
关于 veggerby 的解决方案,如果您尝试在 VB 应用程序上实现它,请小心尝试通过翻译器运行提供的代码。以下将起作用:
Imports System.Web
Imports System.Web.Services
Imports System.Web.SessionState
Public Class SessionHeartbeatHttpHandler
Implements IHttpHandler
Implements IRequiresSessionState
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Session("Heartbeat") = DateTime.Now
End Sub
End Class
Also, instead of calling like heartbeat() function like:
此外,而不是像 heartbeat() 函数那样调用:
setTimeout("heartbeat()", 300000);
Instead, call it like:
相反,称之为:
setInterval(function () { heartbeat(); }, 300000);
Number one, setTimeout only fires once whereas setInterval will fire repeatedly. Number two, calling heartbeat() like a string didn't work for me, whereas calling it like an actual function did.
第一,setTimeout 只触发一次,而 setInterval 会重复触发。第二,像字符串一样调用 heartbeat() 对我不起作用,而像实际函数一样调用它。
And I can absolutely 100% confirm that this solution will overcome GoDaddy's ridiculous decision to force a 5 minute apppool session in Plesk!
而且我绝对可以 100% 确认此解决方案将克服 GoDaddy 在 Plesk 中强制执行 5 分钟 apppool 会话的荒谬决定!
回答by David R Tribble
[Late to the party...]
[聚会迟到了……]
Another way to do this without the overhead of an Ajax call or WebService handler is to load a special ASPX page after a given amount of time (i.e., prior to the session state time-out, which is typically 20 minutes):
在没有 Ajax 调用或 WebService 处理程序开销的情况下执行此操作的另一种方法是在给定时间后(即,在会话状态超时之前,通常为 20 分钟)加载一个特殊的 ASPX 页面:
// Client-side JavaScript
function pingServer() {
// Force the loading of a keep-alive ASPX page
var img = new Image(1, 1);
img.src = '/KeepAlive.aspx';
}
The KeepAlive.aspx
page is simply an empty page which does nothing but touch/refresh the Session
state:
该KeepAlive.aspx
页面只是一个空页面,除了触摸/刷新Session
状态之外什么都不做:
// KeepAlive.aspx.cs
public partial class KeepSessionAlive: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Refresh the current user session
Session["refreshTime"] = DateTime.UtcNow;
}
}
This works by creating an img
(image) element and forcing the browser to load its contents from the KeepAlive.aspx
page. Loading that page causes the server to touch (update) the Session
object, extending the session's expiration sliding time window (typically by another 20 minutes). The actual web page contents are discarded by the browser.
这通过创建img
(图像)元素并强制浏览器从KeepAlive.aspx
页面加载其内容来工作。加载该页面会导致服务器接触(更新)该Session
对象,从而延长会话的到期滑动时间窗口(通常再延长 20 分钟)。浏览器会丢弃实际的网页内容。
An alternative, and perhaps cleaner, way to do this is to create a new iframe
element and load the KeepAlive.aspx
page into it. The iframe
element is hidden, such as by making it a child element of a hidden div
element somewhere on the page.
另一种可能更简洁的方法是创建一个新iframe
元素并将KeepAlive.aspx
页面加载到其中。该iframe
元素是隐藏的,例如通过使其成为div
页面上某处隐藏元素的子元素。
Activity on the page itself can be detected by intercepting mouse and keyboard actions for the entire page body:
可以通过拦截整个页面正文的鼠标和键盘操作来检测页面本身的活动:
// Called when activity is detected
function activityDetected(evt) {
...
}
// Watch for mouse or keyboard activity
function watchForActivity() {
var opts = { passive: true };
document.body.addEventListener('mousemove', activityDetected, opts);
document.body.addEventListener('keydown', activityDetected, opts);
}
I cannot take credit for this idea; see: https://www.codeproject.com/Articles/227382/Alert-Session-Time-out-in-ASP-Net.
我不能相信这个想法;请参阅:https: //www.codeproject.com/Articles/227382/Alert-Session-Time-out-in-ASP-Net。