- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
session 过期后向用户显示消息的最佳方式是什么?
到那时,用户应该被注销并被重定向到起始页面。
我可以使用 javascript 将用户重定向到起始页面。我只想在开始页面上显示一条消息。
最佳答案
此答案的先前版本包含一些简单的来源,用于解决不再存在的问题。
场景是他想收到通知之前 session 超时,以便可以采取行动。
目前尚不清楚它是 asp.net session 还是表单例份验证票,但确实是同一个问题。
基本上相当于异步 session 状态管理,而不触发 session /票证续订。 ajax 应用程序的共同愿望。
解决方案非常简单,但并不完全直截了当。有很多问题需要处理,但我提出了一个对简单 session 状态和表单例份验证都可靠的解决方案。
它由一个非常轻量级的 httpmodule 和随附的客户端脚本库组成,有效的代码行数也不多于 50 或 60 行。
该策略是提供一个 http 端点,该端点可以查询 session 的到期状态或形成票证,而无需更新它们。该模块只是位于管道的前面,并为几个“虚拟”端点提供 javascript 日期和一个非常简单的 js lib 来进行调用。
演示和源代码在这里:AsynchronousSessionAuditor
你们中的一些人想知道为什么我会关心这个,但可能你们中的更多人会说,是的,是的,这太痛苦了。我知道我过去曾提出过易碎的臭味解决方法,对此我感到非常满意。
它可以在标准回发模型应用程序或更可能是 ajax 应用程序中提供服务。
还...
您可以了解更多关于 Http 请求生命周期的信息 here和 here .如果有兴趣,请了解更多关于在 asp.net 端点上使用原始 xmlhttp here
删除以前的尖峰代码。如果您有兴趣,请查看修订历史。
以下是相关的源文件。完整的引用实现可从上面提供的链接获得......
HttpModule
// <copyright project="AsynchronousSessionAuditor" file="AsynchronousSessionAuditorModule.cs" company="Sky Sanders">
// This source is a Public Domain Dedication.
// http://spikes.codeplex.com
// Attribution is appreciated.
// </copyright>
using System;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
namespace Salient.Web.Security
{
/// <summary>
/// AsynchronousSessionAuditorModule provides a mechanism for auditing the lifecycle
/// of an ASP.Net session and/or an ASP.Net FormsAuthentication cookie in the interest
/// of providing better monitoring and control of a user session. This is becoming more
/// important as more and more web apps are single page apps that may not cycle a page for
/// many minutes or hours.
///
/// Storing a token in the Asp.net Session was for many years the default authentication strategy.
/// The are still valid applications for this techique although FormsAuthentication has far
/// surpassed in security and functionality.
///
/// What I am providing is a manner in which to transparently monitor the expiration status of each
/// by implementing a module that recognizes two virtual endpoints:
///
/// http://mysite/.aspnetsession
/// http://mysite/.formsauthticket
///
/// By making a request to these urls you will be delivered a javascript date in numeric form that
/// represents the expiration dateTime of either the current ASP.Net session, if any, or the current
/// FormsAuthentication ticket expiration, if any.
///
/// If the requested item does not exists, zero is returned. Any value served by this module should
/// be cast to a date and compared with Now. If less than you should take action. You should have
/// taken action on the client before the session timed out, aided by the output of this module, but
/// hey, nobody is perfect.
/// </summary>
public class AsynchronousSessionAuditorModule : IHttpModule
{
// note: these must remain in sync with the string keys in the javascript
private const string AspSessionAuditKey = ".aspnetsession";
private const string FormsAuthAuditKey = ".formsauthticket";
#region IHttpModule Members
public void Init(HttpApplication context)
{
// this is our audit hook. get the request before anyone else does
// and if it is for us handle it and end. no one is the wiser.
// otherwise just let it pass...
context.BeginRequest += HandleAuditRequest;
// this is as early as we can access session.
// it is also the latest we can get in, as the script handler is coming
// right after and we want to beat the script handler to the request
// will have to set a cookie for the next audit request to read in Begin request.
// the cookie is used nowhere else.
context.PostAcquireRequestState += SetAuditBugs;
}
public void Dispose()
{
}
#endregion
private static void SetAuditBugs(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication) sender;
if ((app.Context.Handler is IRequiresSessionState || app.Context.Handler is IReadOnlySessionState))
{
HttpCookie sessionTimeoutCookie = new HttpCookie(AspSessionAuditKey);
// check to see if there is a session cookie
string cookieHeader = app.Context.Request.Headers["Cookie"];
if ((null != cookieHeader) && (cookieHeader.IndexOf("ASP.NET_SessionId") >= 0) &&
!app.Context.Session.IsNewSession)
{
// session is live and this is a request so lets ensure the life span
app.Context.Session["__________SessionKicker"] = DateTime.Now;
sessionTimeoutCookie.Expires = DateTime.Now.AddMinutes(app.Session.Timeout).AddSeconds(2);
sessionTimeoutCookie.Value = MilliTimeStamp(sessionTimeoutCookie.Expires).ToString();
}
else
{
// session has timed out; don't fiddle with it
sessionTimeoutCookie.Expires = DateTime.Now.AddDays(-30);
sessionTimeoutCookie.Value = 0.ToString();
}
app.Response.Cookies.Add(sessionTimeoutCookie);
}
}
private static void HandleAuditRequest(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication) sender).Context;
bool formsAudit = context.Request.Url.PathAndQuery.ToLower().StartsWith("/" + FormsAuthAuditKey);
bool aspSessionAudit = context.Request.Url.PathAndQuery.ToLower().StartsWith("/" + AspSessionAuditKey);
if (!formsAudit && !aspSessionAudit)
{
// your are not the droids i am looking for, you may move along...
return;
}
double timeout;
// want to know forms auth status
if (formsAudit)
{
HttpCookie formsAuthCookie = context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (formsAuthCookie != null)
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(formsAuthCookie.Value);
timeout = MilliTimeStamp(ticket.Expiration);
}
else
{
timeout = 0;
}
}
// want to know session status
else
{
// no session here, just take the word of SetAuditBugs
HttpCookie sessionTimeoutCookie = context.Request.Cookies[AspSessionAuditKey];
timeout = sessionTimeoutCookie == null ? 0 : Convert.ToDouble(sessionTimeoutCookie.Value);
}
// ensure that the response is not cached. That would defeat the whole purpose
context.Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetNoStore();
// the money shot. a javascript date.
context.Response.Write(timeout.ToString());
context.Response.Flush();
context.Response.End();
}
/// <summary>
/// Found Code: http://forums.asp.net/t/1044408.aspx
/// </summary>
/// <param name="TheDate"></param>
/// <returns></returns>
private static double MilliTimeStamp(DateTime TheDate)
{
DateTime d1 = new DateTime(1970, 1, 1);
DateTime d2 = TheDate.ToUniversalTime();
TimeSpan ts = new TimeSpan(d2.Ticks - d1.Ticks);
return ts.TotalMilliseconds;
}
}
}
// <copyright project="AsynchronousSessionAuditor" file="AsynchronousSessionAuditor.js" company="Sky Sanders">
// This source is a Public Domain Dedication.
// http://spikes.codeplex.com
// Attribution is appreciated.
// </copyright>
var AsynchronousSessionAuditor = {
/// this script really should be served as a resource embedded in the assembly of the module
/// especially to keep the keys syncronized
pollingInterval: 60000, // 60 second polling. Not horrible, except for the server logs. ;)
formsAuthAuditKey: ".formsauthticket", // convenience members
aspSessionAuditKey: ".aspnetsession",
errorCallback: function(key, xhr) {
/// <summary>
/// Default behavior is to redirect to Default and provide the xhr error status text
/// in the loggedout query param.
///
/// You may replace this default behaviour with your own handler.
/// e.g. AsynchronousSessionAuditor.errorCallback = myMethod;
/// </summary>
/// <param name="key" type="String"></param>
/// <param name="xhr" type="XMLHttpRequest"></param>
window.location = "Default.aspx?loggedout=Error+" + xhr.statusText;
},
timeoutCallback: function(key, xhr) {
/// <summary>
/// Default behavior is to redirect to Default and provide the key value
/// in the loggedout query param.
///
/// You may replace this default behaviour with your own handler.
/// e.g. AsynchronousSessionAuditor.timeoutCallback= myMethod;
/// </summary>
/// <param name="key" type="String"></param>
/// <param name="xhr" type="XMLHttpRequest"></param>
window.location = "Default.aspx?loggedout=" + key;
// or just refresh. you will be sent to login.aspx
},
statusCallback: function(value) {
/// <summary>
/// Default behavior is to do nothing, which is not very interesting.
/// This value is set when AsynchronousSessionAuditor.init is called
/// </summary>
/// <param name="value" type="String">
/// The responseText of the audit request. Most certainly is a JavaScript Date
/// as a number. Just cast to date to get the requested expiration dateTime.
/// e.g. var exp = new Date(parseFloat(value)); if (isNaN(exp)){this should never happen}
/// </param>
window.location = "Default.aspx?loggedout=" + key;
// or just refresh. you will be sent to login.aspx
},
createXHR: function() {
/// <summary>
/// This xhr factory is not the best I have see.
/// You may wish to replace it with another or
/// use your favorite ajax library to make the
/// call.
/// </summary>
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
else {
throw new Error("Could not create XMLHttpRequest object.");
}
return xhr;
},
auditSession: function(key) {
/// <summary>
/// Make a request that will be serviced by the audit module to determine the
/// state of the current FormsAuthentication ticket or Asp.Net session
///
/// The return value is a JavaScript date, in numeric form, that represents the
/// expiration of the item specified by key.
/// Just cast it to date, i.e. new Date(parseFloat(xhr.resposeText))
/// </summary>
/// <param name="key" type="String">
/// the server key for the item to audit.
///
/// use ".formsauthticket" to get the expiration dateTime for the forms authentication
/// ticket, if any.
///
/// use ".aspnetsession" to get the expiration of the current ASP.Net session.
///
/// Both have convenience members on this object.
/// </param>
var xhr = AsynchronousSessionAuditor.createXHR();
xhr.open("GET", key, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status != 200) {
AsynchronousSessionAuditor.errorCallback(key, xhr);
}
else {
var timeout = parseFloat(xhr.responseText)
if (isNaN(timeout) || (new Date(timeout) < new Date())) {
AsynchronousSessionAuditor.timeoutCallback(key, xhr);
}
else {
AsynchronousSessionAuditor.statusCallback(xhr.responseText);
}
}
}
};
xhr.send(null);
},
init: function(key, statusCallback) {
// set the statusCallback member for reference.
AsynchronousSessionAuditor.statusCallback = statusCallback;
// check right now
AsynchronousSessionAuditor.auditSession(key);
// and recurring
window.setInterval((function() { AsynchronousSessionAuditor.auditSession(key) }), AsynchronousSessionAuditor.pollingInterval);
}
};
function callScriptMethod(url) {
/// <summary>
///
/// Simply makes a bogus ScriptService call to a void PageMethod name DoSomething simulating
/// an async (Ajax) call.
/// This resets the session cookie in the same way a postback or refresh would.
///
/// The same would apply to a ScriptService enabled XML Webservice call.
/// </summary>
var xhr = AsynchronousSessionAuditor.createXHR();
xhr.open("POST", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status != 200) {
alert("script method call failed:" + xhr.statusText);
}
}
};
xhr.setRequestHeader("content-type", "application/json");
var postData = null;
xhr.send(postData);
}
<script src="AsynchronousSessionAuditor.js" type="text/javascript"></script>
<script type="text/javascript">
function reportStatus(value) {
/// <summary>
/// In a typical session/ticket lifetime you might display a warning at T-5 minutes that the session
/// is expiring and require an action.
/// </summary>
document.getElementById("sessionTimeout").innerHTML = "Session expires in " + parseInt((new Date(parseFloat(value)) - new Date()) / 1000) + " seconds.";
}
function init() {
// default is 60 seconds. Our session is only 1 minute so lets get crazy and poll every second
AsynchronousSessionAuditor.pollingInterval = 1000;
AsynchronousSessionAuditor.init(AsynchronousSessionAuditor.aspSessionAuditKey, reportStatus);
}
</script>
关于asp.net - 在 asp.net 中 session 超时时通知用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2234348/
我试图对 ASP.Net MVC 有一个高层次的理解,我开始意识到它看起来很像原始的 ASP 脚本。过去,我们将“模型”/业务逻辑代码组织到 VBScript 类或 VB COM 组件中。 当然,现在
我已经搜索了一段时间,但似乎找不到答案。 我想在我的旋转木马中显示一个计数器,左边是当前项目(工作),左边是项目总数。 我的代码:
. 最佳答案 Scott Gu 称这些为代码块。这就是我的看法。 http://weblogs.asp.net/scottgu/archive/2010/04/06/new-lt-gt-syntax
我有一个使用 Visual Studio 2010/.net 4/VB 制作的网站。 我真的很喜欢我发现的 FAQ 系统的布局,因为它很简单,但它是经典的 asp。所以,显然,我不能包括我的母版页布局
好吧,对于你们许多人来说,这个问题可能有一个非常明显的答案,但它让我难住了。 我有一个 asp.net Web 表单,上面有两个控件(嗯,不止这两个,但我们将重点关注这些) - 第一个是 asp:dr
当我将 ASP.NET 复选框控件设置为 asp.net 更新面板的异步回发触发器时,EventName 属性是什么? 最佳答案 我相信它是 CheckedChanged。 关于asp.net - a
我有一个用经典 asp 编写的(巨大的)网站。现在我必须切换到 vb.net (razor)。有没有办法将这两个结合起来直到切换完成? 有没有办法让应用程序与经典的 asp 和 vb.net 一起工作
I am creating a products page, where the user selects an option in a radiobuttonlist for example, an
我最近将一个经典的 ASP 应用程序转换为 ASP.NET 3.5,但我觉得我的经典 ASP 版本要快一些(我不知道可能买家会后悔)。 所以你们能帮我解决这个问题吗,让我知道哪个更快,asp、asp.
从本周开始,我被要求开始学习如何使用 ASP 开发网站。我通过 XNA 对 C# 有一定的经验,所以这部分对我来说并不是什么麻烦。 我一直在关注Music Store Tutorial这需要我设置一个
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
我想将一些表单变量发布到经典 ASP 页面中。我不想改变经典的 ASP 页面,因为需要完成大量的工作,以及消耗它们的页面数量。 经典的 ASP 页面需要将表单变量 Username 和 Userpas
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
在某种程度上,这可能是一个异端问题。我们有一个大型站点,其中许多页面仍在ASP中。通常,并没有真正动态的,而是包括(通过SSI或Server.Execute)定期重新生成的HTML块。看起来好像是一个
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我有一个遗留的 ASP 应用程序——在不久的某个时候——需要迁移到 ASP.Net 2.0(以与也在 2.0 中的其他应用程序兼容)。 对于这类事情是否有最佳实践,即作为第一步将当前 html、vbs
我目前在一家公司工作,该公司使用 ASP.NET Webforms 和旧 ASP 页面的组合进行 Web 开发。这对于他们当前的项目来说效果很好,但我想说服/建议他们切换到 ASP.NET MVC,因
我有一个经典的 asp 应用程序。我想将该页面的竞赛表格发布到 Asp.Net 表格。原因是我想在进入数据库之前使用我在 Asp.Net 页面中内置的大量逻辑进行验证,而我对 asp 不太了解。更不用
我知道在 ASP.NET MVC 中,您可以拥有移动 View 并执行类似 Index.mobile.cshtml 的操作。和 _Layout.mobile.cshtml并且服务器知道将这些 View
我需要从一些服务器端 c#.net 代码中调用经典 asp 页面上的 VBscript 函数 - 有谁知道一种干净的方法来做到这一点?在 .net 中重写函数不是一种选择。 我会再解释一下这个问题..
我是一名优秀的程序员,十分优秀!