用户会话过期后,如何重定向到页面?
我目前正在使用ASP.NET 2.0框架的Web应用程序上工作。当用户会话过期时,我需要重定向到某个页面,例如SessionExpired.aspx。项目中有很多页面,因此向站点的每个页面添加代码并不是一个好的解决方案。我有MasterPages,但我认为这可能会有所帮助。
谢谢!
解决方案
通常,当用户"登录"时,我会将HtmlMeta控件添加到母版页的Page.Header.Controls集合中。将其设置为Refresh到具有适当超时时间的SessionExpired.aspx页,这很好。
另一种方法是告诉浏览器在一定时间后自行重定向(通过javascript)...但这始终可以由用户停用。
添加或者更新Web.Config文件以包括此文件或者类似文件:
<customErrors defaultRedirect="url" mode="RemoteOnly"> <error statusCode="408" redirect="~/SessionExpired.aspx"/> </customErrors>
如果我正确理解," Session_End"将在内部触发并且没有与之关联的HTTP上下文:
http://forums.asp.net/t/1271309.aspx
因此,我认为我们不能使用它来重定向用户。我看到其他人建议在global.ascx文件中使用" Session_OnStart()"事件:
http://forums.asp.net/p/1083259/1606991.aspx
我没有尝试过,但是可以将以下代码放入" global.ascx"中:
void Session_OnStart() { if (Session.IsNewSession == false ) { } else { Server.Transfer("SessionExpired.aspx", False); } }
会话到期时,我们无法重定向用户,因为没有浏览器请求重定向:
- 如果用户在会话超时(默认为20分钟)内访问了网站,则会话尚未结束,因此我们无需重定向它们。
- 如果用户在会话超时后访问站点,则会话已经结束。这意味着它们将处于新会话的上下文中-已为旧会话触发了Session_OnEnd,相反,我们将为新会话获取Session_OnStart。
因此,除了客户端功能(例如JavaScript计时器等)之外,我们还需要在Session_OnStart中处理重定向,但是显然我们需要将其与重新访问网站的用户区分开。一种选择是在会话开始时设置会话cookie(即,没有过期的cookie,这样它将一直持续到关闭浏览器),然后在Session_OnStart中查找该cookie(如果存在的话)是返回会话的过期用户,如果不是,则为新用户。
显然,我们仍然可以使用Session_OnEnd在服务器端进行整理,这只是客户端交互对我们不可用。
我们是否在Session对象中放置了应该始终存在的内容?换句话说,如果他们登录,则可能在会话中添加了诸如UserID之类的东西
Session("UserID") = 1234
因此,如果是这种情况,则可以在母版页的代码隐藏中添加一些内容来检查该值。像这样的东西:
Dim UserID As Integer = 0 Integer.TryParse(Session("UserID"), UserID) If UserID = 0 Then Response.Redirect("/sessionExpired.aspx") End If
我们使用表单身份验证,并在Page_Load方法中调用此方法
private bool IsValidSession() { bool isValidSession = true; if (Context.Session != null) { if (Session.IsNewSession) { string cookieHeader = Request.Headers["Cookie"]; if ((null != cookieHeader) && (cookieHeader.IndexOf("ASP.NET_SessionId") >= 0)) { isValidSession = false; if (User.Identity.IsAuthenticated) FormsAuthentication.SignOut(); FormsAuthentication.RedirectToLoginPage(); } } } return isValidSession; }
我们可以在Session_Start事件的global.asax中进行处理。我们可以在该请求中检查会话cookie。如果会话cookie存在,则会话已过期:
public void Session_OnStart() { if (HttpContext.Current.Request.Cookies.Contains("ASP.NET_SessionId") != null) { HttpContext.Current.Response.Redirect("SessionTimeout.aspx") } }
las,我还没有找到找到会话cookie名称的任何优雅方法。
我们是否希望在下一个请求上进行重定向,还是在没有用户干预的情况下立即进行重定向?如果我们希望在没有用户干预的情况下进行重定向,则可以在母版页上使用ClientScript.RegisterStartupScript注入一些JavaScript,以在客户端会话期满时重定向客户端。
System.Text.StringBuilder sb = new System.Text.StringBuilder(); String timeoutPage = "SessionExpired.aspx"; // your page here int timeoutPeriod = Session.Timeout * 60 * 1000; sb.AppendFormat("setTimeout(\"location.href = {0};\",{1});", timeoutPage, timeoutPeriod); Page.ClientScript.RegisterStartupScript(this.GetType(), "timeourRedirect", sb.ToString(), true);
从这里的代码
namespace PAB.WebControls
{
使用系统;
使用System.ComponentModel;
使用System.Web;
使用System.Web.Security;
使用System.Web.UI;
[DefaultProperty("Text"), ToolboxData("<{0}:SessionTimeoutControl runat=server></{0}:SessionTimeoutControl>")] public class SessionTimeoutControl : Control { private string _redirectUrl; [Bindable(true), Category("Appearance"), DefaultValue("")] public string RedirectUrl { get { return _redirectUrl; } set { _redirectUrl = value; } } public override bool Visible { get { return false; } } public override bool EnableViewState { get { return false; } } protected override void Render(HtmlTextWriter writer) { if (HttpContext.Current == null) writer.Write("[ *** SessionTimeout: " + this.ID + " *** ]"); base.Render(writer); } protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); if (this._redirectUrl == null) throw new InvalidOperationException("RedirectUrl Property Not Set."); if (Context.Session != null) { if (Context.Session.IsNewSession) { string sCookieHeader = Page.Request.Headers["Cookie"]; if ((null != sCookieHeader) && (sCookieHeader.IndexOf("ASP.NET_SessionId") >= 0)) { if (Page.Request.IsAuthenticated) { FormsAuthentication.SignOut(); } Page.Response.Redirect(this._redirectUrl); } } } } }
}