从.NET 3.0升级到3.5:在Web Garden中,设置为StateServer的站点将恢复为InProc

时间:2009-02-08 23:50:17

标签: .net asp.net session state state-server

情景:

运行运行.NET 3.0的服务器和在启用了Web园的应用程序池中运行的ASP.NET网站(进程数:3)。 web.config配置如下:

    <sessionState
      cookieless="UseCookies"
      cookieName=".authz"
      mode="StateServer"
      regenerateExpiredSessionId="true"
      stateConnectionString="tcpip=127.0.0.1:42424"
      timeout="60"
      useHostingIdentity="true" />

现在将计算机升级到.NET 3.5 SP1。重新启动服务器。结果:不再在w3wp.exe的实例之间维护会话,就好像所有会话都还原为InProc一样。目前的解决方法是减少到1个工作进程。

奇怪的是:不同服务器上的相同代码没有遇到任何问题。我之前遇到过这个问题,但重启后神奇地消失了。我已经重启了一次,但到目前为止还没有快乐。

比较两台服务器的两台machine.configs和web.configs:相同。

Someone else has experienced this problem,但没有答案。

有什么想法吗?我真的难以接受这个。

1 个答案:

答案 0 :(得分:11)

所以,这个很棒。

如果满足以下所有条件,则会出现问题:

  • 您正在运行Windows Server 2003(IIS 6.0)和ASP.NET 2.0网站。
  • 该网站配置为使用Web Gardens,其中最大工作进程数大于1.因此,您已将应用程序配置为使用进程外会话存储;在这种情况下,ASP.NET状态服务在本地计算机上运行。
  • 应用程序池标识不是设置为NETWORK SERVICE,而是设置为您根据deployment best practice创建的自定义低权限用户帐户。
  • 您运行一个更新.NET框架的安装程序;就我而言,这是从.NET 3.0到.NET 3.5 SP1的更新。

当升级完成并重新启动服务器时,您会发现刷新页面时会丢失会话变量,因为只有1/3的机会获得原始工作进程以满足您的原始请求。但这并不重要,因为您正在使用ASP.NET状态服务。什么破了?

使用ASP.NET状态服务时,ASP.NET使用一个名为machineKey的值来加密和/或散列要存储的所有会话数据(我不知道它是加密还是散列,或者两者都是,但这不是这次讨论的重要区别)。这样,当任何工作进程使用会话标识符从服务请求数据时,可以确保数据在存储在外部数据源中时未被篡改。

如果您在Web场中,则可能在machineKey文件中定义了静态web.config,并且不会发生此问题。但对于单服务器Web园方案,您可能依赖于默认的machineKey设置,该设置对于ASP.NET 2.0应用程序设置为AutoGenerate,IsolateApps。这意味着ASP.NET会自动生成应用程序池独有的计算机密钥。它根据某种算法重新生成此密钥,但这对于此讨论并不重要。

生成的值通常存储在HKLM\SOFTWARE\Microsoft\ASP.NET\2.0.50727.0\AutoGenKeys\{SID of the Application Pool Identity}下的注册表中。但是.NET Framework安装程序错误(我确实认为这是一个错误)会破坏此注册表项,并且为了加重侮辱,会重置此密钥的权限,以便您的自定义应用程序池标识无法写入注册表项创建新的机器密钥。

结果是,在Web园中旋转的每个工作进程都使用它自己及时生成的机器密钥的内存副本,从而有效地创建了Web场景。例如,工作进程A旋转,看到没有AutoGenKey条目存在(实际上,它甚至不能读取它),生成它自己的并开始使用它来散列发送到ASP的数据.NET状态服务。它尝试将此新计算机密钥保存到注册表项,但无提示失败。工作进程B旋转,看到没有AutoGenKey条目存在,生成自己的条目并开始使用 来散列数据...你会看到它的去向。

现在结果是您使用三个不同的机器密钥对会话数据进行了哈希处理。虽然会话标识符的数据存在,但三个工作进程中有两个会将其拒绝为无效/篡改,因为它使用自己的密钥。

您可以通过在machineKey文件中明确设置自定义web.config来解决此问题。

或者您可以在命令提示符处重新运行aspnet_regiis.exe -ga MachineName\ApplicationPoolUserName以修复损坏的权限。

你的问题解决了。是时候睡觉了。


6月30日更新:根据我在Microsoft Connect上对此问题的报告,Microsoft已表明他们已修复安装程序,以便在升级到.NET时不会发生此行为4.所有未来的3.0 / 3.5升级仍然可能发生,所以我会留下这个问题/答案。