【问题标题】:Share Session between two web sites using asp.net and state server使用 asp.net 和状态服务器在两个网站之间共享会话
【发布时间】:2011-03-27 05:14:19
【问题描述】:

我在 IIS 7.5 下的两台不同机器上托管了两个完全相同的网站。 ASP.NET 状态服务正在我的机器上运行,并且使用以下代码在两个站点中更新了 web.config:

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

允许远程连接在注册表中设置为 1,以便第二个网站访问状态服务器。

两个网站都有相同的机器密钥:

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

另外,两个站点都在 IIS 中配置为具有相同的标识符。

我想要做的是这两个站点共享相同的会话数据,例如能够执行以下操作:

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

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

问题是我无法完成这个测试,真的无法理解我做错了什么。

有什么好办法吗?

【问题讨论】:

    标签: c# asp.net iis state


    【解决方案1】:

    我知道这个问题在 5 年前就已经回答了,但今天我想我可以在其中添加更多信息。

    首先,这不是在 2 个 IIS 应用程序之间共享会话数据的官方方式,也不是最流行的方式。 “看似官方”的方式是use SQL Server session

    如果您因任何原因无法使用 SQL Server,那么我们可以稍微调整 IIS 应用程序,以便我们可以使用进程外会话,也就是 StateServer 会话状态模式。

    要让它发挥作用,需要做很多事情:

    1. 2 个应用程序的会话 cookie 必须设置为相同的域名。例如
    <httpCookies domain=".your.site"/>
    
    1. 机器密钥必须匹配。您可以使用标准的Web.config field encryption 使其更安全,但这是可选的。
    <machineKey validationKey="[your_key]" 
        decryptionKey="[your_decryption_key]" validation="SHA1" />
    
    1. 会话状态模式设置为状态服务器

    将 (1)、(2)、(3) 放在一起:

    <system.web>
        <httpCookies domain=".your.site"/>
        <machineKey validationKey="your_key" decryptionKey="your_decryption_key" validation="SHA1" />
        <sessionState mode="StateServer" timeout="60" />
        ...
    
    1. 应用名称必须匹配。如果没有,则只能共享会话 ID,而不能共享会话数据。问题是您无法在 Web.config 中配置应用程序名称。然而,我们可以创建自己的配置,然后通过反射注入它。只需将以下代码放入 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);
          }
      }
      

      致谢pfemianiLi Chen,还有一个我不记得是谁把它放在代码项目评论中的人。请注意,pfeemiani 的答案对我不起作用,但结合李晨的帖子可以。

    2. 确保ASP .NET state service 正在运行。这是现在保存会话数据的地方。

    【讨论】:

    • 这对我有用。特别是第 4 点是其他 SO 答案中缺少的内容。
    【解决方案2】:

    您需要一种方法来说服您的浏览器发送相同的 ASP.NET 会话 cookie,而不管它访问哪个站点。

    如果请求中不存在 cookie,则将使用该密钥创建一个新会话。

    我认为您可以通过一些偷偷摸摸的 DNS 配置让浏览器保留密钥 - 如果您将 http://website1.mydomain.com/http://website2.domain.com/ 分配为您的站点地址,然后将 ASP.NET 会话 cookie 的域设置为“domain.com”,然后您的浏览器会将其发送到两个站点,并且会话应该被共享。

    您还可以在 ASP.NET 中使用无 cookie 模式,并从生成的 URL 中获取会话 ID。

    【讨论】:

    • 因此,如果在 Firefox 中我将 ASP.NET_SessionId cookie 更改为在两个 url 中完全相同,例如它可能会起作用。对吗?
    • 是的,我想是的。您还可以使用 Fiddler 覆盖请求中的 cookie 值。
    • 关于无cookie模式的警告:它非常不安全。会话 ID 在 URL 中,因此人们可以简单地获取它并以您的身份登录,而无需任何用户/密码。
    【解决方案3】:

    两个 asp.net web 应用程序之间的共享会话

    请参考以下网址

    http://www.freshcodehub.com/Article/48/sharing-session-between-two-aspnet-web-applications

    【讨论】:

      【解决方案4】:

      我的问题是我的两个应用程序使用了不同的主要版本的 Owin 库。一旦我确保两个应用程序之间的所有 Owin 库共享相同的版本,我就可以按照 Hoàng Long 发布的答案来让它工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-13
        • 1970-01-01
        • 2017-08-10
        • 1970-01-01
        • 1970-01-01
        • 2012-09-17
        • 2012-08-30
        相关资源
        最近更新 更多