- 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/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!