views:

4665

answers:

2

When my ASP.Net session times out (and forms authentication as well) and I try to hit a page, I am automatically redirected to my default login.aspx page.

Before the page loads I need to determine whether this is a timeout situation and if so - redirect to timeout.aspx.

The articles below specify that if IsNewSession is true, and a sessionID cookie exists - then you have a timeout situation.

However in my testing I have the situation where I timeout and try to log back in again and IsNewSession is equal to true and the sessionId cookie is still hanging around (because it stays for a entire browser session), therefore it says I've timed-out again when I'm just trying to log back in.

Is there a better way to do all this?

Technique is decribed here and here.

In my 'global.asax' file I have:

void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
        // Check if session state is enabled in web.config
        if (Context.Session == null) return;

        if (Session["user"] == null) 
        {
            if (Session.IsNewSession)
            {                    
                HttpCookie sessionCookie = Request.Cookies["ASP.NET_SessionId"];
                if ((null != sessionCookie) && !string.IsNullOrEmpty(sessionCookie.Value))
                {
                    /* Session Timeout! */
                    FormsAuthentication.SignOut(); //just in case not done yet
                    Session.Abandon();
                    Response.Redirect("timeout.aspx");
                }
                else
                {
                    // Cookie didn't exist - must be a brand new login
                    return;
                }
            }
            else
            {
                // If there is no session data and the session is not new then it must be the postback of the login screen.
                if ((HttpContext.Current.Request.Path.ToLower().LastIndexOf("/login.aspx") >= 0) && (Request.HttpMethod == "POST"))
                {
                    return;
                }
            }
        }    
}
+4  A: 

You are trying to distinguish between a timeout session and a session that was manully logged out?

Your problem is that since the session data is gone all you have to go on is that a new request coming in has created a new session and the request coming in carries a session ID cookie (indicating that it had been logged in before).

There are two approaches.

Cookie:

First in your login page you could create an additional cookie that indicates the login status of the user. When the user manually logs out the cookie value is modified to indicate the logout. A request after a session has timed out will in addition to having IsNewSession true will also have a login status cookie showing the user is still logged in, thus indicating the user hadn't manually chosen to logout.

Database:

A second approach is to store sessionIDs in a DB table along with logged in status. When a logon is successful enter the sessionID into a LoggedOnSessions table. When the user manually logs off delete the sessionID from the table. Hence your timeout detection can include a look up of the session ID in the table if present it was a timeout (at this point you should probably remove the ID as well).

For housekeeping purposes you should include an expiry datetime field which is set for much longer than any realistic logon period (a week for example). On a regular basis (e.g., weekly) delete entries in the table that have expired.

My preference is the database approach I hate setting cookies because it irks me that that cookie is being sent with every request but is rarely needed.

AnthonyWJones
A: 

You may also look in you web.config file under the tag authentication. This should look something like this:

<authentication mode="Windows">
  <forms defaultUrl="Default.aspx" loginUrl="Login.aspx" name=".aspxAuth">
  </forms>
</authentication>

Notice the attribute mode, it probably says Forms instead of Window in you web.config file. In this case, if you lose your session and then click on any link (let's say SalesChart.aspx) ASP.NET will take you directly to Login.aspx codebehind instead of SalesChart.aspx codebehind which is particularly annoying.

If you try Windows mode, you will be taken to the requested page (SalesChart.aspx) everytime, and then decide on your own what action to take if session is lost.