Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Share Session between two web sites using asp.net and state server

I have two exactly the same web sites hosted in two different machines under IIS 7.5. ASP.NET state service is running on my machine and the web.config is updated in both sites with the following code:

<sessionState mode="StateServer" stateConnectionString="tcpip=192.168.1.77:42424" cookieless="false" timeout="120"/>

The allow remote connection is set to 1 in registry in order for the second web site to access the state server.

Both web sites have the same machine key:

<machineKey validationKey="7CB8DF6872FB6B35DECD3A8F55582350FEE1FAB9BE6B930216056C1B5BA69A4C5777B3125A42C4AECB4419D43EC12F168FD1BB887469798093C3CAA2427B2B89" decryptionKey="02FC52E4C71544868EE297826A613C53537DF8FDAF93FA2C64E9A5EF0BA467FB" validation="SHA1" decryption="AES" />

Additionally both sites are configured in IIS to have the same Identifier.

What I want to do is that both these sites share the same session data for example being able to do the following:

// At web site 1: 
Session["key"] = "value"

and

// At web site 2:
// Read session value from the other web site
string result = Session["key"]

The problem is that I can't manage to accomplish this test and really can't understand what I am doing wrong.

Any idea that might help?

like image 925
ppolyzos Avatar asked Aug 09 '10 09:08

ppolyzos


People also ask

How do you pass session values between two applications?

If you want to share session between two applications just for the authentication purpose then I would suggest you to go for one of the Single Sign-On options rather than sharing sessions between two applications. Otherwise to share sessions between two applications you need to load both the apps under same app domain.

How do you maintain a session across multiple applications?

Well you just need to have both apps pointing at a database using the same connection string, then both apps will be able to see the same data.

What is difference between session and application state?

"Application state" = the state of the application, which is the same for all users. "Session State" = state specific to this particular user session. Each user has separate session state.

Which is better session or ViewState?

The basic difference between these two is that the ViewState is to manage state at the client's end, making state management easy for end-user while SessionState manages state at the server's end, making it easy to manage content from this end too.


2 Answers

I'm aware that this question was answered 5 years ago, yet today I think I can put some more information into it.

First, this is not the official way to share session data between 2 IIS applications, or the most popular way. The "seemingly official" way is to use SQL Server session.

In case you can't use SQL server for any reason, then we can tweak the IIS applications a bit so that we can use Out-of-process session, aka StateServer session state mode.

To make it works, there are quite a few things to make right:

  1. Session cookie of 2 application must be set at same domain name. E.g.
<httpCookies domain=".your.site"/>
  1. Machine key must be matched. You can do standard Web.config field encryption to make it more secure, but that's optional.
<machineKey validationKey="[your_key]" 
    decryptionKey="[your_decryption_key]" validation="SHA1" />
  1. Session state mode set to state server

Putting (1), (2), (3) together:

<system.web>
    <httpCookies domain=".your.site"/>
    <machineKey validationKey="your_key" decryptionKey="your_decryption_key" validation="SHA1" />
    <sessionState mode="StateServer" timeout="60" />
    ...
  1. Application name must be matched. If not, only the session ID could be shared, but not session data. The problem is that you cannot configure your application name inside Web.config. Yet we can create our own configuration then inject it by reflection. Just put the following code in Global.asax.cs:

    public override void Init()
    {
        base.Init();
        try
        {
            // Get the app name from config file...
            string appName = ConfigurationManager.AppSettings["ApplicationName"];
            if (!string.IsNullOrEmpty(appName))
            {
                foreach (string moduleName in this.Modules)
                {
                    IHttpModule module = this.Modules[moduleName];
                    SessionStateModule ssm = module as SessionStateModule;
                    if (ssm != null)
                    {
                        FieldInfo storeInfo = typeof(SessionStateModule).GetField("_store", BindingFlags.Instance | BindingFlags.NonPublic);
                        SessionStateStoreProviderBase store = (SessionStateStoreProviderBase)storeInfo.GetValue(ssm);
                        if (store == null) //In IIS7 Integrated mode, module.Init() is called later
                        {
                            FieldInfo runtimeInfo = typeof(HttpRuntime).GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic);
                            HttpRuntime theRuntime = (HttpRuntime)runtimeInfo.GetValue(null);
                            FieldInfo appNameInfo = typeof(HttpRuntime).GetField("_appDomainAppId", BindingFlags.Instance | BindingFlags.NonPublic);
                            appNameInfo.SetValue(theRuntime, appName);
                        }
                        else
                        {
                            Type storeType = store.GetType();
                            if (storeType.Name.Equals("OutOfProcSessionStateStore"))
                            {
                                FieldInfo uribaseInfo = storeType.GetField("s_uribase", BindingFlags.Static | BindingFlags.NonPublic);
                                uribaseInfo.SetValue(storeType, appName);
                            }
                        }
                    }
                }
            }
    
        }
        catch (Exception ex)
        {
            log.Error(ex.Message, ex);
        }
    }
    

    Credits go to pfemiani, Li Chen, and someone I can't remember who putting it together in a code project's comment. Please note that pfemiani's answer does not work for me, yet combining it with Li Chen's post does.

  2. Make sure ASP .NET state service is running. It is where session data would be saved now.

like image 136
Hoàng Long Avatar answered Sep 19 '22 14:09

Hoàng Long


You'll need a way to convince your browser to send the same ASP.NET session cookie regardless of which site it visits.

If the cookie isn't present on the request, then a new session will get created with that key.

I think you can get the browser to retain the key with some sneaky DNS configs - if you assign http://website1.mydomain.com/ and http://website2.domain.com/ to be the addresses of your sites, then set the domain of the ASP.NET session cookie to "domain.com", then your browser will send it to both sites and the session should be shared.

You may also be able to use cookieless mode with ASP.NET, and grab the session ID from the generated URLs.

like image 40
mwalker Avatar answered Sep 22 '22 14:09

mwalker