Session Variables - Doc Request - http

Sessions' variables
In all web app you can get/set sessions' variables
PHP:
$foo = $_SESSION['myVar'];
.NET (MVC, in Controller):
using System.Web.Mvc;
// ...
var foo = Session["myVar"];
I am looking for some detailed informations on sessions' variables :
Their initial purpose (what problems did they aimed to address ?)
Common use cases
Storage
Where is it stored on the system ?
Hard drive, RAM, ...
Who is storing it?
Client / Server
I guess it's server-side, so what is managing it ?
Web Server (Apache, IIS, ...) / Web App
What is the lifetime of a session's variable ?
The session, right. So when do a session start, when does it end and how do the system know when it can get rid of these variables (GC mechanism) ?
Security
Known security flaws ?
PS: I would like to allow people here to build a good documentation about this concept. Feel free to edit the question if you think some questions should be added or edited.

Purpose
Session Variables were created primarily to deal with the stateless behavior of the HTTP protocol. Because each page request was handled pretty much completely separately from each other page request, developers wanted ways to tie strings of requests together. The canonical example of this is a login page that authenticates the user and then changes the behavior of pages requested after login.
To help with this problem, many languages and/or frameworks provided the concept of a Session Variable which would let the developer store data that would be associated with a specific browser and would persist across separate requests from that same browser.
So, to take logins as an example, on the first request from a new browser, the Session Variable would be blank. Then the user would fill out authentication information and assuming it was correct, on the server side the code would set the Session Variable for that browser to contain some sort of identifier to say that his browser was authenticated. Then during subsequent requests the code could check that identifier in the Session Variable to do some specific code that required logging in.
Another common use case would be for a "wizard" workflow. You might have a multi-page form that you want the user to fill in over several separate requests. As the user fills out the form, you can add the values to the session until the user gets to the end of the form at which time you could save it in some more permanent storage.
Storage and Management
There are many ways to store Session Variables. Any sort of persistent storage that is persistent across requests will work. Probably the most basic way is to just create a separate file for each session. PHP does this by taking a session ID that it has stored as a cookie in a browser and then looks for a file with a named derived from the session ID.
You can also store Session Variables in databases, shared memory, or even in the cookie itself. Ruby on Rails stores Session Variables by encrypting the data and then setting the cookie to the encrypted data. So the session gets stored in the user's browser itself.
Most typically the Session Variable is associated with a cookie that is stored in web browser in some way. This cookie is usually managed automatically by the language or framework that the web server application is written in. The language or framework detects a new session and creates a new Session Variable that it provides to the web server application via some sort of API. The web server application can then use the API to store information in the Session Variable, to delete it, create a new one, etc... Usually the framework has some default value for the lifetime of the session, but usually this is adjustable via the API. I think the most typical default lifetime is the the lifetime of the browser process via a cookie that has a lifetime associated with the user's browser process.
Security
There are a lot of security issues around Session Variables because they are typically used to manage authorization and authentication in web applications.
For example, many applications set the session lifetime just using the lifetime associated with the cookie. Many login systems want to force the user to re-login after a specified time, but you can't trust the browser to expire the cookie when you tell it to. The browser could be buggy, could be written by a malicious person, or manipulated by the user herself to adjust the lifetime of the cookie. So if the Session Variable API you are using relies on the cookie lifetime, you may need to have a secondary mechanism that forces the Session Variable to expire even if the cookie doesn't.
Some other security issues involve storage. If you store A Session ID in a cookie and then use that Session ID as your file name to store the Session Variable in, a malicious browser can change the Session ID in the cookie to another ID and then requests from that browser would start using some other browser's session file.
Another issue is stolen session information. Through XSS or packet inspection, session information can be stolen from a users browser session and then used by a malicious user to access the other user's accounts. This sort of problem is typically mitigated by using SSL to protect the session in transit.
This page explains a lot of the security issues when using PHP's implementation of Session Variables. Ruby on Rails has a similar page that outlines the security issues with Session Variables for that platform.

So, I will be taking this question on under two considerations:
1. I am answering under PHP guidelines.
2. I am assuming that a shared hosting service is used.
Storage
With the use of shared hosting, the php.ini file holds this answer. The file is created, physically, at the path you specify through the "session.save_path" line within the php.ini file.
Source: php.net Manual
Who Stores Session
The session is TECHNICALLY stored by the SERVER but at request, obviously, by the client. So, answer: SERVER.
Source: session_start
Who Manages It
If your session.save_path is set to go somewhere on a shared hosting server, then they control the GC that destroys it or ignores it until later. Actually, instances have happened for me where other clients within the shared hosting server had their session_gc.maxlifetime at a MUCH shorter amount than I did, therefore causing my session files to be destroyed in the amount of time that THEY set (other shared users). To get around this, edit your "session.save_path" to within your OWN file tree.
Lifetime
As said previously, "session.gc_maxlifetime" controls this file's "expiration". Along with this, the "session.gc_probability" and "session.gc_divisor" should be considered, and set to "1" and "100", respectively. Google search this for further explanation.
Source: session.gc_maxlifetime
Security
I'm going to let php.net handle this, but here's the link!
Source: Security

I take an ASP.NET application scenario as an example.
In ASP.NET/MVC HttpContext.Current.Session provides access to RAM that is managed by the Server (WebServer/AppServer, IIS). In the case of the Internet Information Server, the RAM used is located inside a so called Application Pool and used by one or more Apps running inside the Web-/AppServer. The structure from the programmer's point of view is a Dictionary which means for access via C# that you can use the this[] operator to write to and read from the Session object.
// write access
var CurrentArticle = 123456;
Session["CurrentArticle"] = CurrentArticle;
//...
// read access
var CurrentArticle = 0;
CurrentArticle = (int)Session[nameof(CurrentArticle)];
The Session object provided by .NET will be created in the method Session_Start and deleted in Session_End. However, you don't have to use the System's default Session Store and can implement your own, i.e. like this:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Web;
// using MyOtherStuff;
namespace MyStuff.Server.Context
{
public class HttpSessionState : HttpSessionStateBase
{
Dictionary<string, object> _sessionStorage = new System.Collections.Generic.Dictionary<string, object>();
public override object this[string name]
{
get
{
if (HttpContext.Current == null || HttpContext.Current.Session == null)
if (!_sessionStorage.ContainsKey(name))
return null;
else return _sessionStorage[name];
return HttpContext.Current.Session[name];
}
set
{
if (HttpContext.Current == null || HttpContext.Current.Session == null)
_sessionStorage[name] = value;
else HttpContext.Current.Session[name] = value;
}
}
}
public class Current
{
/// <summary>
/// Objects stored in Cache expire after some time; compare Application
/// </summary>
public static ExpiringCache Cache = new ExpiringCache();
/// <summary>
/// Objects stored in Application don't expire
/// </summary>
public static Application Application = new Application();
public static HttpSessionState Session = new HttpSessionState();
private static System.Web.HttpServerUtility server;
public static System.Web.HttpServerUtility Server
{
get
{
if (System.Web.HttpContext.Current != null)
return Context.Current.Server;
if (server != null)
return server;
server = new System.Web.HttpApplication().Server;
if (server != null)
return server;
throw new NotSupportedException("HDitem.ApplicationServices.Current was not initialized (server)");
}
set { server = value; }
}
}
//..
}
Every new Browser connecting to your server creates a new session. If you don't care about the data from recent sessions of the same user (if your app has users) than you are probably done here.
If you want to re-connect a new session to one or more previous sessions, i.e. identified by some combination of data you have available about this user (e.g. through the request, a cookie or alike) or in the easiest form the authentication of the user than you might want to store the data of the session in Session_End rather than deleting it and recover it in Session_start or any time thereafter (as soon as you have enough data about the user of this session to identify her. In this case you need any form of Session Persistence (presumably this boils down to a Hard Disk or SSD to refer to your question) which in this case can come in any form of per-user-based storage, sometimes stored in a user-profile in a database or any file format like XML- or JSON-based.
So in other words: I don't want to generalize too much here but Session Storage is ideally very fast Memory Storage, potentially saved to any external storage if Session Persistence is implemented.
The above mentioned Session Storage is located on the server side. Modern browsers have a built in localstore that can be accessed via JavaScript. This local storage can also be used to create a session memory that can be used differently from the server-side session but can of course be synchronized in form of explicit requests or attachment to requests (cookie).

Related

Storing an ASP.NET Session in Redis and reading it in ServiceStack

All,
We have several ASP.NET websites that are using the RedisSessionStateProvider for session storage. We are just starting to spin up an instance of ServiceStack, and I would like to pass the sessionId from ASP.NET to ServiceStack, then use the stored values from Redis in ServiceStack sessions.
So far I have been able to pass the sessionID in the header, retrieve it in my plugin, and get the value matching that sessionId from Redis back as a string.
My problem is is a typed object going into Redis from ASP.NET, but I can't get it as the type object coming out in ServiceStack.
Any and all suggestions are appreciated.
Thanks,
B
ServiceStack Sessions are completely decoupled/independent from ASP.NET Sessions and its Session Provider model. As they're 2 completely different technologies they're incompatible with each other, you'll need a separate "migration step" to extract out data from ASP.NET Session State, populate your Typed Custom UserSession and save it in ServiceStack.
ServiceStack Sessions are simply your Typed UserSession persisted in the registered Caching Provider at a key identified from the Cookie SessionId.
Navigating all User Sessions in Cache
The Inspecting Persisted User Sessions illustrates how User Sessions are serialized POCO's stored in the Registered ICacheClient at the following key:
urn:iauthsession:{SessionId}
Where {SessionId} is either the users ss-id or ss-pid cookie depending on whether the user was authenticated with RememberMe=true which instructs ServiceStack to save the session against the ss-pid permanent cookie - this preference is stored in the ss-opt=perm cookie.
Since they're just plain POCO's stored at a predictable key format, we can easily iterate through all user sessions by using the ICacheClient API's directly, e.g:
var sessionPattern = IdUtils.CreateUrn<IAuthSession>(""); //= urn:iauthsession:
var sessionKeys = Cache.GetKeysStartingWith(sessionPattern).ToList();
var allSessions = Cache.GetAll<IAuthSession>(sessionKeys);

Application level variables in web api c#

I am in a situation where requirement is to keep an application level object in web api which can be accessed by all requests. I know one can use HttpContext.Current but that is not required since HttpContext is only for the liftime of request. I need a solution where i can keep an object that all requests can access and update as required.
Use a static class to hold your application level objects. static classes and static data members are created once for the application lifetime and all ASP.NET requests can access them.
I learnt it the hard way. Some time back, I mistakenly created a static field to hold customer-specific database connection string, in a ASP.NET Web API project and it became a mess. On each customer's login it was being set (overridden) in the code and the requests from the previously logged customers were using this newly set static SQL connection string for their queries. It was an embarrassing situation when customer's inadvertently saw each other's data.
You could use SessionState (per session).
I.e.
Session["YourDataKey"] = ApplicationLevelObject;
And then check the session state variable on each request that requires it.
However if you require the object for longer, I.e. every single user session, then I would suggest persisting your object to a database. You could use an ORM such as Entity Framework.
Cheers

Session state access in Web API across domains

I have a ASP.Net API implementation, where to store and access the data / variables across consecutive calls, I am using a session state object as shown below and it can be successfully accessed in the multiple calls to separate calls by a browser:
// Access the current session object
var blSession = HttpContext.Current.Session;
// create the BL object using the user id
BL accessBL = new BL(userID);
// Store the Bl object in the session object dictionary
blSession["UserBL"] = accessBL;
I have to enable the following setting in the Global.asax, for the Session object to be accessible:
protected void Application_PostAuthorizeRequest()
{
// Enable session state in the web api post authorization
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
Issue comes in when the WebAPI shown above has to be accessed via another ASP.Net MVC client, which is separately hosted on a different machine, at that time same consecutive calls do not maintain the state as shown above and thus it leads to an exception, since the consecutive calls rely on session data to proceed.
I have seen a similar issue when I seen the similar issue when I use the Fiddler Debugger, as it gets hosted as a web proxy, so consecutive calls through that too fails, since it does not maintain the state. In my understanding, issue is due to setting the Cookie across domain, which doesn't seem to work across domains due to security reason
I know a workaround is to use an application wide variable like Cache, but please suggest if you have a way to get the SessionState work. Let me know if you need more details.
If you have not setup an alternative way to do SessionState, then the default behavior is to do it InMemory on the server. This is why you are seeing issues when the request is handled by a different ASP.NET server.
Web API calls are meant to be stateless. That is, they should not perform like a classic ASP.NET application that relies on the framework to store user specific information in Session variables across HTTP requests. For each call, pass in a user-specific identifier or token that you can then use to lookup information stored in your backend. You can store this information in your database or a distributed cache like MemCache for faster retrieval.

Using static variable in ASP.NET web-service like cross thread

Is it possible to use it with everything like in threads, with locking?
Main idea is to track whether some web-method is already invoked by same user, so we want to block more than X calls in a minute. We would keep some data in relevant HashTable.
ASP.NET Sessions are dependent on cookies, which are easily circumvented by malicious users. Since malicious users seem to be your problem, ASP.NET sessions aren't the solution.
You could write a wrapper class containing a static Dictionary<UserID, List<DateTime>> allowing operations on the dictionary only with 1-2 methods and properly locking it.
eg
class UserLogger
{
private Dictionary<int, List<DateTime>> _visits;
public bool AddPageVisit(int userID)
{
// lock dictionary
// add or update entry for the user,
// remove from all entries the datetimes older than a minute
// remove entries without datetimes
// check if number of datetimes for the user > max allowed
// unlock dictionary
}
}
class RestrictedController
{
private static UserLogger _userLogger;
}
Disclaimer: I just wrote this pseudo-code in the answer, it may contain typo's.
There is a big disadvantage of asp.net session. It locks executing same sessionId requests unless session is in ReadOnly state. I haven't use it in that way but it think it can solve your task.
ASP.NET Session State Overview
Concurrent Requests and Session State
Access to ASP.NET session state is exclusive per session, which means
that if two different users make concurrent requests, access to each
separate session is granted concurrently. However, if two concurrent
requests are made for the same session (by using the same SessionID
value), the first request gets exclusive access to the session
information. The second request executes only after the first request
is finished. (The second session can also get access if the exclusive
lock on the information is freed because the first request exceeds the
lock time-out.) If the EnableSessionState value in the # Page
directive is set to ReadOnly, a request for the read-only session
information does not result in an exclusive lock on the session data.
However, read-only requests for session data might still have to wait
for a lock set by a read-write request for session data to clear.

What should I do if the current ASP.NET session is null?

In my web application, I do something like this to read the session variables:
if (HttpContext.Current.Session != null && HttpContext.Current.Session["MyVariable"] != null)
{
string myVariable= (string)HttpContext.Current.Session["MyVariable"];
}
I understand why it's important to check why HttpContext.Current.Session["MyVariable"] is null (the variable might not have been stored in the Session yet or the Session has been reset for various reasons), but why do I need to check if HttpContext.Current.Session is null?
My understanding is that the session is created automatically by ASP.NET therefore HttpContext.Current.Session should never be null. Is this assumption correct? If it can be null, does it mean I should also check it before storing something in it:
if (HttpContext.Current.Session != null)
{
HttpContext.Current.Session["MyVariable"]="Test";
}
else
{
// What should be done in this case (if session is null)?
// Is it possible to force the session to be created if it doesn't exist?
}
Yes, the Session object might be null, but only in certain circumstances, which you will only rarely run into:
If you have disabled the SessionState http module, disabling sessions altogether
If your code runs before the HttpApplication.AcquireRequestState event.
Your code runs in an IHttpHandler, that does not specify either the IRequiresSessionState or IReadOnlySessionState interface.
If you only have code in pages, you won't run into this. Most of my ASP .NET code uses Session without checking for null repeatedly. It is, however, something to think about if you are developing an IHttpModule or otherwise is down in the grittier details of ASP .NET.
Edit
In answer to the comment: Whether or not session state is available depends on whether the AcquireRequestState event has run for the request. This is where the session state module does it's work by reading the session cookie and finding the appropiate set of session variables for you.
AcquireRequestState runs before control is handed to your Page. So if you are calling other functionality, including static classes, from your page, you should be fine.
If you have some classes doing initialization logic during startup, for example on the Application_Start event or by using a static constructor, Session state might not be available. It all boils down to whether there is a current request and AcquireRequestState has been run.
Also, should the client have disabled cookies, the Session object will still be available - but on the next request, the user will return with a new empty Session. This is because the client is given a Session statebag if he does not have one already. If the client does not transport the session cookie, we have no way of identifying the client as the same, so he will be handed a new session again and again.
The following statement is not entirely accurate:
"So if you are calling other functionality, including static classes, from your page, you should be fine"
I am calling a static method that references the session through HttpContext.Current.Session and it is null. However, I am calling the method via a webservice method through ajax using jQuery.
As I found out here you can fix the problem with a simple attribute on the method, or use the web service session object:
There’s a trick though, in order to access the session state within a web method, you must enable the session state management like so:
[WebMethod(EnableSession = true)]
By specifying the EnableSession value, you will now have a managed session to play with. If you don’t specify this value, you will get a null Session object, and more than likely run into null reference exceptions whilst trying to access the session object.
Thanks to Matthew Cosier for the solution.
Just thought I'd add my two cents.
Ed
If your Session instance is null and your in an 'ashx' file, just implement the 'IRequiresSessionState' interface.
This interface doesn't have any members so you just need to add the interface name after the class declaration (C#):
public class MyAshxClass : IHttpHandler, IRequiresSessionState
In my case ASP.NET State Service was stopped. Changing the Startup type to Automatic and starting the service manually for the first time solved the issue.
ASP.NET Technical Articles
SUMMARY: In ASP.NET, every Web page
derives from the System.Web.UI.Page
class. The Page class aggregates an
instance of the HttpSession object for
session data. The Page class exposes
different events and methods for
customization. In particular, the
OnInit method is used to set the
initialize state of the Page object.
If the request does not have the
Session cookie, a new Session cookie
will be issued to the requester.
EDIT:
Session: A Concept for Beginners
SUMMARY: Session is created when user
sends a first request to the server
for any page in the web application,
the application creates the Session
and sends the Session ID back to the
user with the response and is stored
in the client machine as a small
cookie. So ideally the "machine that
has disabled the cookies, session
information will not be stored".

Resources