【问题标题】:ASP.NET Push Redirect on Session Timeout会话超时时的 ASP.NET 推送重定向
【发布时间】:2010-10-03 20:28:44
【问题描述】:

我正在寻找有关在会话到期时自动推送用户(即没有回发)的网站背后的技术的教程、博客条目或一些帮助。任何帮助表示赞赏

【问题讨论】:

  • “推送用户”是什么意思?

标签: asp.net redirect session-timeout server-push


【解决方案1】:

通常,您设置会话超时,并且您可以另外添加页眉以自动将当前页面重定向到您在会话超时之前清除会话的页面。

来自http://aspalliance.com/1621_Implementing_a_Session_Timeout_Page_in_ASPNET.2

namespace SessionExpirePage
{
    public partial class Secure : System.Web.UI.MasterPage
    {
        public int SessionLengthMinutes
        {
            get { return Session.Timeout; }
        }
        public string SessionExpireDestinationUrl
        {
            get { return "/SessionExpired.aspx"; }
        }
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            this.PageHead.Controls.Add(new LiteralControl(
                String.Format("<meta http-equiv='refresh' content='{0};url={1}'>", 
                SessionLengthMinutes*60, SessionExpireDestinationUrl)));
        }
    }
}

SessionExpireDestinationUrl 应该链接到您清除会话和任何其他用户数据的页面。

当刷新标头过期时,它会自动将它们重定向到该页面。

【讨论】:

    【解决方案2】:

    您不能真正从您的网站“推送”客户。您的站点将响应来自客户的请求,但事实就是如此。

    这意味着您需要编写一些客户端 (Javascript) 来确定用户何时超时,可能通过将当前时间与他们在站点 cookie 中的最近时间(您更新每次用户访问您网站上的页面时的当前时间),如果差异大于一定数量,则重定向。

    (我注意到有些人提倡创建一个脚本,该脚本将在页面上经过一定时间后转发用户。这在简单的情况下有效,但如果用户在网站上打开了两个窗口,并且正在使用一个窗口很多,而另一个窗口不是那么多,不是那么多的窗口会突然将用户重定向到转发页面,即使用户一直在网站上。另外,它不是真正与您在服务器端进行的任何会话保持同步。另一方面,编码当然更容易,如果这足够好,那就太好了!)

    【讨论】:

      【解决方案3】:

      部分,使用 META 刷新标签,如下所示:
      <meta http-equiv="refresh" content="0000; URL=target_page.html">
      

      其中 0000 是以秒为单位的会话超时,target_page.html 是要重定向到的页面地址。

      【讨论】:

      • 你知道吗?我爱你 :) 简单,简单,只是工作,非常适合像我这样的 asp.net 初学者:)
      【解决方案4】:

      使用自定义页面类和 Javascript 也可以实现。

      创建一个自定义的pagebase类并将常用功能代码写入该类。通过这个类,我们可以将常用的功能分享给其他网页。在这个类中,我们需要继承 System.Web.UI.Page 类。将以下代码放入Pagebase类中

      PageBase.cs

      namespace AutoRedirect
      {
          public class PageBase : System.Web.UI.Page
          {
              protected override void OnPreRender(EventArgs e)
              {
                  base.OnPreRender(e);
                  AutoRedirect();
              }
      
              public void AutoRedirect()
              {
                  int int_MilliSecondsTimeOut = (this.Session.Timeout * 60000);
                  string str_Script = @"
                     <script type='text/javascript'> 
                         intervalset = window.setInterval('Redirect()'," +
                             int_MilliSecondsTimeOut.ToString() + @");
                         function Redirect()
                         {
                             window.location.href='/login.aspx'; 
                         }
                     </script>";
      
                 ClientScript.RegisterClientScriptBlock(this.GetType(), "Redirect", str_Script);
              }
          }
      }
      

      上面的AutoRedirect函数将用于在会话到期时重定向登录页面,通过使用javascript window.setInterval,这个window.setInterval重复执行一个javascript函数,具有特定的时间延迟。在这里,我们将时间延迟配置为会话超时值。一旦达到会话到期时间,就会自动执行重定向功能并将控制权转移到登录页面。

      OriginalPage.aspx.cs

      namespace appStore
      {
          public partial class OriginalPage: Basepage
          {
              protected void Page_Load(object sender, EventArgs e)
              {
              }     
          }
      }
      

      OriginalPage.aspx

      <%@ Page Language="C#" AutoEventWireup="true" CodeFile="OriginalPage.aspx.cs" Inherits="AutoRedirect.OriginalPage" %>
      

      Web.config

      <system.web>    
          <sessionState mode="InProc" timeout="3"></sessionState>
      </system.web>
      

      注意: 使用 Javascript 的优点是您可以在 location.href 之前的警报框中显示自定义消息,这对用户来说非常有意义。 如果您不想使用 Javascript,您也可以选择元重定向

      public void AutoRedirect()
      {
          this.Header.Controls.Add(new LiteralControl(
              String.Format("<meta http-equiv='refresh' content='{0};url={1}'>",
                  this.Session.Timeout * 60, "login.aspx")));
      }
      

      【讨论】:

        【解决方案5】:

        只需将此代码 sn-p 复制并粘贴到您的 Web.Config 文件中即可:

        <authentication mode="Forms">
          <forms loginUrl="~/Login.aspx" slidingExpiration="true" timeout="29" />
        </authentication>
        
        <sessionState timeout="30" mode="InProc" cookieless="false" />
        

        你可以把这条线放到你的 Site.Master 中:

        Response.AppendHeader("Refresh", 
                              Convert.ToString((Session.Timeout * 60)) + 
                              ";URL=~/Login.aspx");
        

        【讨论】:

        • Response.AppendHeader("Refresh", Convert.ToString((Session.Timeout * 60)) + ";URL=" & System.Web.Security.FormsAuthentication.LoginUrl);
        【解决方案6】:

        我作为初学者使用 MVC3 ASp.net,我尝试了许多解决方案来解决我的会话问题(因为我在我的代码中使用 Session 变量,并且在超时后我没有会话值而我保持使用它我只是发现我的问题出在配置文件中。身份验证和 sessionState 之间的超时应该如此接近。所以他们同时杀死(空)//添加超时 1 和 2 进行测试..它应该在至少 29 和 30

        我也使用了其他方式:

        开始于:

            protected void Session_Start(object src, EventArgs e)
            {
                if (Context.Session != null)
                {
                    if (Context.Session.IsNewSession)//|| Context.Session.Count==0)
                    {
                        string sCookieHeader = Request.Headers["Cookie"];
                        if ((null != sCookieHeader) && (sCookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
                        {
                            //if (Request.IsAuthenticated)
                             FormsAuthentication.SignOut();
                             Response.Redirect("/Account/LogOn");
                        }
                    }
                }
        
            }
        
            protected void Session_End(object sender, EventArgs e)
            {
             //Code that runs when a session ends. 
             //Note: The Session_End event is raised only when the sessionstate mode 
             //is set to InProc in the Web.config file. If session mode is set to StateServer
              //or SQLServer, the event is not raised. 
                Session.Clear();          
            }
        

        还有:

        public class SessionExpireFilterAttribute : ActionFilterAttribute
        {
        
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                HttpContext ctx = HttpContext.Current;
        
                // check if session is supported
                if (ctx.Session != null)
                {
        
                    // check if a new session id was generated
                    if (ctx.Session.IsNewSession)
                    {
                        // If it says it is a new session, but an existing cookie exists, then it must
                        // have timed out
                        string sessionCookie = ctx.Request.Headers["Cookie"];
                        if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0))
                        {
                            ctx.Response.Redirect("~/Home/LogOn");
                        }
                    }
                }
        
                base.OnActionExecuting(filterContext);
            }
        }
        

        甚至与 Ajax 合作解决会话问题:

            protected override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                if (Session.Count == 0 || Session["CouncilID"] == null)
                    Response.Redirect("/Account/LogOn");
        
                if (Request.IsAjaxRequest() && (!Request.IsAuthenticated || User == null))
                {
                    filterContext.RequestContext.HttpContext.Response.StatusCode = 401;
                }
                else
                {
                    base.OnActionExecuting(filterContext);
                }
            }
        
            [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
            public class AuthorizeUserAttribute : AuthorizeAttribute
            {
                protected override bool AuthorizeCore(HttpContextBase httpContext)
                {
                    if (!httpContext.Request.IsAjaxRequest())
                    {//validate http request.
                        if (!httpContext.Request.IsAuthenticated
                            || httpContext.Session["User"] == null)
                        {
                            FormsAuthentication.SignOut();
                            httpContext.Response.Redirect("~/?returnurl=" + httpContext.Request.Url.ToString());
                            return false;
                        }
                    }
                    return true;
                }
        
                protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
                {
                    if (filterContext.HttpContext.Request.IsAjaxRequest())
                    {
                        filterContext.Result = new JsonResult
                        {
                            Data = new
                            {
                                // put whatever data you want which will be sent
                                // to the client
                                message = "sorry, but you were logged out"
                            },
                            JsonRequestBehavior = JsonRequestBehavior.AllowGet
                        };
                    }
                    else
                    {
                        base.HandleUnauthorizedRequest(filterContext);
                    }
                }
        
            }
        

        【讨论】:

          【解决方案7】:

          不幸的是,它无法完成。会话超时仅发生在服务器端,在用户执行某种回发操作之前您不会检测到这一点。

          但是,您可以做的是注入一些 HTML 或 JavaScript 标头代码,这些代码会在会话超时的同一时间段内自动将用户推送到注销页面。这并不能保证完美同步,如果您的用户正在执行一些耗时的项目并且您没有重置时钟,您可能会遇到问题。

          我通常将此代码添加到我的 Page_Load 事件中以完成此操作。

          ' Register Javascript timeout event to redirect to the login page after inactivity
            Page.ClientScript.RegisterStartupScript(Me.GetType, "TimeoutScript", _
                                                        "setTimeout(""top.location.href = 'Login.aspx'""," & _
                                                         ConfigurationManager.AppSettings("SessionTimeoutMilliseconds") & ");", True)
          

          【讨论】:

            【解决方案8】:

            如果您使用以下登录控制器,它会在登录前将您发送到请求的 URL:

               [HttpPost]
                public ActionResult LogOn(LogOnModel model, string returnUrl)
                {
            
                    if (ModelState.IsValid)
                    {
                        if (Membership.ValidateUser(model.UserName, model.Password))
                        {
            
                            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            
                            if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                                && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                            {
                                //return Redirect(returnUrl);
                                if (!String.IsNullOrEmpty(returnUrl))
                                {
                                    return Redirect(returnUrl);
                                }
                                else
                                {
                                  return RedirectToAction("Index", "Home");
                                }
            
                            }
                            else
                            {
                                return RedirectToAction("Index", "Home");
                            }
                        }
                        else
                        {
                            ModelState.AddModelError("", "The user name or password provided is incorrect.");
                        }
                    }
            
                    // If we got this far, something failed, redisplay form
                    return View(model);
                }
            

            【讨论】:

              【解决方案9】:

              当然你需要使用[Authorize]而不是控制器类,甚至是特定的Action。

              [Authorize]
              public class MailController : Controller
              {
              }
              

              【讨论】:

                【解决方案10】:

                正如 Zhaph - Ben Duguid 指出的那样,这对于 AJAX 请求来说很棘手。这是我使用 AJAX 进行这项工作的解决方案(使用 Telerik Web 控件,但我相信它们是使用 ASP.NET AJAX 工具包构建的)。

                简而言之,我推出了自己的滑动到期会话类型的东西。

                在我的 Site.Master 中,我在每次回发(回发或 AJAX 请求,因为 AJAX 请求仍然启动 Page_Load 事件)时更新会话变量:

                protected void Page_Load(object sender, EventArgs e)
                    {
                        if (!this.IsPostBack)
                        {
                            if (this.Request.IsAuthenticated)
                                this.pnlSessionKeepAlive.Visible = true;
                            else
                                this.pnlSessionKeepAlive.Visible = false;
                        }
                
                        if (this.Session["SessionStartDateTime"] != null)
                            this.Session["SessionStartDateTime"] = DateTime.Now;
                        else
                            this.Session.Add("SessionStartDateTime", DateTime.Now);
                    }
                

                然后在我的 site.master 标记中,我包含了一个带有 ASPX 页面的 iframe,我使用“幕后”来检查我的自定义滑动到期是否已过期:

                <asp:Panel runat="server" ID="pnlSessionKeepAlive" Visible="false">
                 <iframe id="frame1" runat="server" src="../SessionExpire.aspx" frameborder="0" width="0" height="0" / >
                 </asp:Panel>
                

                现在在我的 SessionExpire.aspx 页面中,我只是经常刷新页面并检查时间戳是否已过期,如果是,我将重定向到我的 logout.aspx 页面,然后确定将用户发送回哪个登录页面:

                public partial class SessionExpire : System.Web.UI.Page
                {
                    protected void Page_Load(object sender, EventArgs e)
                    {
                        /* We have to do all of this because we need to redirect to 2 different login pages. The default .NET
                         * implementation does not allow us to specify which page to redirect expired sessions, its a fixed value.
                         */
                        if (this.Session["SessionStartDateTime"] != null)
                        {
                            DateTime StartTime = new DateTime();
                            bool IsValid = DateTime.TryParse(this.Session["SessionStartDateTime"].ToString(), out StartTime);
                            if (IsValid)
                            {
                                int MaxSessionTimeout = Convert.ToInt32(ConfigurationManager.AppSettings["SessionKeepAliveMins"]);
                                IsValid = (DateTime.Now.Subtract(StartTime).TotalMinutes < MaxSessionTimeout);
                            }
                
                            // either their session expired or their sliding session timeout has expired. Now log them out and redirect to the correct
                            // login page.
                            if (!IsValid)
                                this.Logout();
                        }
                        else
                            this.Logout();
                
                        // check every 60 seconds to see if the session has expired yet.
                        Response.AddHeader("Refresh", Convert.ToString(60));
                    }
                
                    private void Logout()
                    {
                        this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "TimeoutScript",
                                    "setTimeout(\"top.location.href = '../Public/Logout.aspx'\",\"1000\");", true);
                    }
                }
                

                非常感谢上面发布信息的人,这引导我找到我的解决方案,希望它可以帮助其他人。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2011-08-02
                  • 2011-02-20
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-12-05
                  相关资源
                  最近更新 更多