多个ASP.NET站点如何通过ASP.NET State服务共享Session会话

笔者想实现多个ASP.NET的站点能够共享Session (会话),

 bing, stackoverflow, baidu, FQgoogle找了一大圈,实验N小时,弄到快吐血才找到, 亲测可用,特意转载收藏。


注意: 原作者说到他这种其实是非官方的方式,算是一种hack, 通过反射的方式做的操作,适用于 IIS6 or IIS7 classic mode, IIS7 integrated mode 

但不能确保未来更高版本的IIS是否兼容。 


转载于:https://weblogs.asp.net/lichen/sharing-session-state-over-multiple-asp-net-applications-with-asp-net-state-server

Sharing session state over multiple ASP.NET applications with ASP.NET state server



具体步骤如下:


1. 启用ASP.NET State Service服务



2.修改注册表项 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\aspnet_state\Parameters


如果有ASP.NET站点与ASP.NET STATE服务不在同一台机器上,必须将AllowRemoteConnection 设置为1

Port默认为42424, 你也可以修改成自定义的端口


3. 配置每个ASP.NET站点的WEB.config,使用State服务作为Session管理的提供者

配置放在system.web节点下

<sessionState cookieName="MySessionId" mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" timeout="30"/>
  <machineKey compatibilityMode="Framework20SP1" validationKey="9DBEBFAA6D3AF06F4505D3DA793A784BBB9CC63F2FC2F8CFD90F0E50E7B3E62CF2439C55C83BE1A2704B84B7F7AA720DFB5E2C507F4BB293C2A62E92E183B7AC" decryptionKey="FAC9018DB8D925DA093AB64DA682CB0BBE30B7DA5DF7451F" validation="SHA1" />


mode="StateServer"表示使用asp.net state 服务

stateConnectionString是asp.net state服务的地址, 如果不在本机,将127.0.0.1替换成state服务所在的主机地址,同时

确保防火墙没有限制42424端口或你定义的端口

cookieName是可以将系统默认的存放sessionid的cookie名称改成自定义的,你也可以不设置,使用系统默认的



4. 在Global.asax的init方法里运行下面这段关键代码

   public override void Init()
        {
            base.Init();
            foreach (string moduleName in this.Modules)
            {
                string appName = "MyApp";
                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);
                        }
                    }
                }
            }
        }


5. 如果是跨服务器的话,当你从一个asp.net网站重定向到另外一个网站时,由于cookie无法跨域,需要

你自己想办法能够重定向后的网站能够识别你同时生成SessionId。

   这里你可以用Url带上参数把sessionId传过去,然后在后台用以下代码给浏览器客户端用cookie传回session id

代码如下:   假设你的URL类似 /index?sid=xxxxxxxxxxxxxx

      var Context = System.Web.HttpContext.Current;
      var manager = new SessionIDManager();
      string newID = sid;
      bool redirected = false;
      bool isAdded = false;
      manager.SaveSessionID(Context, newID, out redirected, out isAdded);
      Session["authenticated"] = true;
      Return RedirectToAction("xxxx");   // 需要重定向,这样浏览器下次发出请求就能带上session id, 当前还无法访问共享的session

注意 Session["authenticated"] = true 只是个示例, 测试发现至少要给Session赋一个值,才可能后端会给浏览器返回sessionid 的cookie






posted on 2017-08-03 22:29  omage  阅读(94)  评论(0编辑  收藏  举报