ASP.NET Push Redirect on Session Timeout

前端 未结 10 1837
Happy的楠姐
Happy的楠姐 2020-11-29 21:04

I\'m looking for a tutorial, blog entry, or some help on the technique behind websites that automatically push users (ie without a postback) when the session expires. Any h

相关标签:
10条回答
  • 2020-11-29 21:56

    Usually, you set the session timeout, and you can additionally add a page header to automatically redirect the current page to a page where you clear the session right before the session timeout.

    From 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)));
            }
        }
    }
    

    The SessionExpireDestinationUrl should link to a page where you clear the session and any other user data.

    When the refresh header expires, it will automatically redirect them to that page.

    0 讨论(0)
  • 2020-11-29 21:57

    Just copy and paste this code snippet in your Web.Config file :

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

    You can put this line to your Site.Master :

    Response.AppendHeader("Refresh", 
                          Convert.ToString((Session.Timeout * 60)) + 
                          ";URL=~/Login.aspx");
    
    0 讨论(0)
  • 2020-11-29 21:57

    Well this gets tricky for AJAX requests as Zhaph - Ben Duguid pointed out. Here was my solution to make this work with AJAX (using Telerik web controls but they are built using ASP.NET AJAX toolkit I believe).

    In a nutshell, I rolled my own sliding expiration session type thing.

    In my Site.Master, I am updating a session variable on EVERY postback (postback or AJAX request because AJAX requests still kick off the Page_Load event):

    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);
        }
    

    Then in my markup for my site.master, I included an iframe with a ASPX page I use "behind the scenes" to check and see if my custom sliding expiration has expired:

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

    Now in my SessionExpire.aspx page, I just refresh the page every so often and check if the timestamp has lapsed and if so, I redirect to my logout.aspx page that then determines which login page to send the user back to:

    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);
        }
    }
    

    Many thanks to the people above who posted info, this lead me to my solution and hope it helps others.

    0 讨论(0)
  • 2020-11-29 21:59

    And if you use the following Logon controller, it will send you to the requested URL before logon:

       [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);
        }
    
    0 讨论(0)
提交回复
热议问题