Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
201 views
in Technique[技术] by (71.8m points)

c# - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...