Session state access in Web API across domains - asp.net

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.

Related

Session Variables - Doc Request

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).

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

ASP.NET Web Service very slow when [WebMethod(EnableSession = true)]

I have created a ASMX Web Service which does some Active Directory stuff behind the scene.
As I wish to retain certain information within Web Services under user session, I have decided to put [WebMethod(EnableSession = true)] and start using Session variables.
However, when I turn that option on, the return time from app -> web service -> app has became ridiculously long. (about a minute or more).
If I remove [WebMethod(EnableSession = true)], it is fairly fast.
Anyone know what is going on?
Possible reasons:
Session state is stored out of process (state server/ SQL server) and getting/storing it taking a long time
You are making multiple concurrent requests (including service requests) under the same session. ASP.NET ensures that only one session-full (session read/write) request execute at a time and hence, multiple concurrent requests would queue up.
EDIT :
For #2, obvious solution is to avoid session state use - for example, can you put the relevant information into another store such as cache or database (expensive).
If you are only reading session state in web service then you may take advantage of read-only session state (see IReadOnlySessionState). Read-only session state allows concurrent read-only requests - read/write request will still block all other requests. Now, EnableSession from WebMethod attribute does not support this - it either provides no session or read/write session. So one of the workaround can be to implement your own handler implementing IReadOnlySessionState and then route asmx request to thi handler using a http-module and then switch the handler to default one later. Because your handler requires read-only session state, you will have the read-only session state - see this forum post where such http-module that switches the handler has been given.

Implement second level cache in ASP.Net

Is there any way to use caching in ASP.Net except SQL Server second level cache. As it is the first time to work with caching I want any way with an example. I have found that NHibernate implements this but we are using .netTiers as an application framework.
The Session cache seems to be the appropriate caching mechanism here. The Session cache is a fault-tolerant cache of objects.
Inserting an object
Session["Username"] = "Matt";
Reading an object
string username = (string)Session["Username"];
Removing an object
Session.Remove("Username");
I say fault-tolerant because if the value with the key you specify doesn't exist in the Session cache, it will not through an exception, it will return null. You need to consider that when implementing your code.
One thing to note, if you are using Sql Server or State Server, the objects you can put in the cache need to be serializable.
Memcached is also a very good way to go, as it is very flexible. It is a windows service that runs on any number of machines and your app can talk to the instances to store and retrieve from the cache. Good Article Here

HttpSession Session ID different to FlexSession ID

I have a Flex application which is served via a JSP page. In this page I output the session ID using HttpSession when the page is loaded:
System.out.println("Session ID: " + session.getId());
In a very simple remote object hosted in BlazeDS (called from the flex application using an AMF Channel and standard RemoteObject functionality) I also output the session ID but this time using FlexSession (which as I understand is supposed to wrap around HttpSession).
System.out.println("FlexSession ID: " + FlexContext.getFlexSession().getId());
I would expect both IDs to be the same but this is not the case. The session IDs differ which is causing problems as there is data stored in the HttpSession which I need to be able to access from my remote objects within BlazeDS.
I've exhausted the reading material on BlazeDS and FlexClient/FlexSession/FlexContext but can't see why the FlexSession is not being linked to the HttpSession. Any pointers greatly appreciated.
I feel I must be missing something fundemental here, am I accessing the
I do not think that it is related to the FlashPlayer..is more related to the concept of FlexSession and how BlazeDS/LCDS works. For example you can have an active session even when not using the http channels - when using NIO/RTMP you are bypassing the application server and the http protocol. So it make sense to have an abstract class FlexSession with various implementations.
However when using BlazeDS FlexSession will wrap an HttpSession object internally, and removeAttribute/getAttribute/setAttribute are in fact calling the the same methods from the HttpSession object..so you can access all the data from the HttpSession. If not please provide more details.
However, it will not work when using RTMP channels(which exists only in LCDS by the way), you need to change your design in this case.
Thanks to both answers above I finally found the root cause and thought I'd share it on here.
The reason for differing session IDs was to do with the use of SSL for authentication and the use of AMF Channel rather than Secure AMF. Using the channel for the first time caused a new session to be created (hence the different ID) as the existing session related to the secure version of the site.
Silly configuration mistake but worth passing on - make sure that if using SSL that you're also using Secure AMF connecting to the secure endpoint rather than standard AMF or you'll run into the same session ID problems I faced.
Unfortunately this is just how the Flash player works. I have seen this same behavior many times.
The best solution I found was to establish the HTTP session and pass back the session ID. On the client side, you can then pass the session ID to the Flex application. You then send that ID from Flash to the server and use it to look up the existing session or establish a second session.
You will need to do something like this though, I have not been able to find a way to reliably get Flash to use the same session.

Resources