9

I'm using ASP.NET Session State to keep track of logged in users on my site.

However, one problem I'm running into is that by default ASP.NET session cookies are set to expire when the browser closes.

http://ahb.me/43e

I've tried setting my own ASP.NET_SessionId cookie and modifying the cookie's expiry using something similar to the following code:

Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddMonths(1);

None of these approaches work, they all set a second cookie with the same name.

Is there a way of changing the session cookie's expiry?

5 Answers5

10

Based on links in Joe's answer, I figured out this approach:

public void Application_PostRequestHandlerExecute(object sender, EventArgs e)
{
    UpdateSessionCookieExpiration();
}

/// <summary>
/// Updates session cookie's expiry date to be the expiry date of the session.
/// </summary>
/// <remarks>
/// By default, the ASP.NET session cookie doesn't have an expiry date,
/// which means that the cookie gets cleared after the browser is closed (unless the
/// browser is set up to something like "Remember where you left off" setting).
/// By setting the expiry date, we can keep the session cookie even after
/// the browser is closed.
/// </remarks>
private void UpdateSessionCookieExpiration()
{
    var httpContext = HttpContext.Current;
    var sessionState = httpContext?.Session;

    if (sessionState == null) return;

    var sessionStateSection = ConfigurationManager.GetSection("system.web/sessionState") as SessionStateSection;
    var sessionCookie = httpContext.Response.Cookies[sessionStateSection?.CookieName ?? "ASP.NET_SessionId"];

    if (sessionCookie == null) return;

    sessionCookie.Expires = DateTime.Now.AddMinutes(sessionState.Timeout);
    sessionCookie.HttpOnly = true;
    sessionCookie.Value = sessionState.SessionID;
}

This code can be inserted in Global.asax.cs.

Tom Pažourek
  • 9,582
  • 8
  • 66
  • 107
2

I would suggest you use FormsAuthentication to track logged in users. You can use a persistent FormsAuthenticationCookie to achieve what you want.

Or if you really want to use Session State, try this technique.

Joe
  • 122,218
  • 32
  • 205
  • 338
  • The FormsAuthCookie approach just allows returning users to skip the forms login if they re-connect within a specific time window. It doesn't maintain any state that they may have previously created on the server. – ChrisW Jun 09 '10 at 21:25
  • @ChrisW - "It doesn't maintain any state that they may have previously created on the server" - of course not, such state should be persisted, e.g. to a database, e.g. using Profile. – Joe Jun 10 '10 at 04:25
  • The link to the article is dead (or redirects to something else). Can anyone summarize the technique there? I cannot find any other resource related to that. Thanks. – Tom Pažourek Sep 13 '16 at 09:48
  • @Tom, I would recommend using FormsAuthentication, but I think the article is available here: http://devproconnections.com/development/create-persistent-id-cookies – Joe Sep 13 '16 at 10:00
  • @Joe: Thanks for quick response. I'm looking for ways to store small amounts data for non-registered users. Is it possible to use FormsAuthentication for users that aren't authenticated as well? – Tom Pažourek Sep 13 '16 at 10:03
  • @TomPažourek - no you can't use Forms authentication for that. A cookie is the obvious solution. – Joe Sep 13 '16 at 11:07
  • @Joe: Thanks for the insights. I'm afraid using cookies would allow users to view or mess with the values. And rather then trying to implement some sort of encryption mechanisms in cookie values, I'd just use the session state. – Tom Pažourek Sep 13 '16 at 12:45
  • @Tom - encrypting cookies would be the usual way to avoid viewing or tampering by users. But if Session state meets your requirements, that may be a reasonable alternative. – Joe Sep 13 '16 at 12:52
  • @Joe: Encrypted cookies might actually work alright for me as I don't need much data stored there. I'm guessing encrypting cookies with something like `MachineKey` wouldn't be too hard. Thanks for suggestions. – Tom Pažourek Sep 13 '16 at 12:57
  • @TomPažourek - yes, encrypting with MachineKey is easy (and using other standard encryption APIs isn't hard either). Just be aware that in a web farm environment you need to use the same MachineKey on all servers in the farm: https://msdn.microsoft.com/en-us/library/ff649308.aspx#paght000007_webfarmdeploymentconsiderations – Joe Sep 13 '16 at 13:04
1

Just a guess: Maybe editing the session.configuration inside the web.config could change the cookie-expiration? You can take a look here?

OlafW
  • 700
  • 6
  • 22
  • 1
    This does not work. The timeout specified in the sessionstate configuration is only applicable to the sessionstore. Not the Cookie stored on the browser. – hreinn1000 May 11 '11 at 16:03
1

I think trying to keep session alive for a long time is the wrong approach and limits your scalability. The session cookie is pointing to a specific session that's being maintained by IIS on the server. In general, you want session to close after the user closes their browser so as to not consume all of the available server resources for inactive users. You want session for a departing user to close and the resources made available to a new arriving user. That's why the session cookie expires.

If you want to maintain some user state after the user closes their browser, you can always look at something like Profile. Or, if this is for something like a shopping cart, you can persist your shopping cart in a database and then reconnect that to the user when they log on again.

ChrisW
  • 9,151
  • 1
  • 20
  • 34
  • 1
    I'm facing this problem with a shopping cart, but I was planning on using the session id for non-registered users, so your last suggestion won't fit the bill. Any other ideas? – Drazen Bjelovuk Sep 22 '14 at 02:36
  • @DrazenBjelovuk: I'm facing the same issue, I have a shopping cart in the database and wanted to store a reference to it in the session for non-registered users. Can I ask how did you solve the problem? Any suggestions? Thank you. – Tom Pažourek Sep 13 '16 at 09:49
  • @TomPažourek Hi Tom. I ended up using a separate cookie representing a randomly generated ID of a newly created temporary cart record in the database, with an expiry field set to the same value as the cookie's expiry. On registration, the products of that cart (represented in a CartProduct table) would simply have their previously empty UserID field set to the ID of the newly created user account, and the temporary cart record deleted. [ERD snippet](http://i.imgur.com/l6cdCVe.png). – Drazen Bjelovuk Sep 14 '16 at 01:39
  • @DrazenBjelovuk: Thanks for sharing, it looks like it might be a good approach. – Tom Pažourek Sep 14 '16 at 10:52
1

Tom's answer almost worked for me, except for casting the cookie into a variable and setting its properties. I had to set the properties of the object directly like so:

HttpContext.Current.Response.Cookies["ASP.NET_SessionId"].Expires = expiryDate;
HttpContext.Current.Response.Cookies["ASP.NET_SessionId"].HttpOnly = true;
HttpContext.Current.Response.Cookies["ASP.NET_SessionId"].Value = sessionState.SessionID;

I still cast the cookie into a variable to check if it's null, and return if so.

stairie
  • 85
  • 7