使用 ASP.NET 会话状态服务跨应用程序共享会话

Posted

技术标签:

【中文标题】使用 ASP.NET 会话状态服务跨应用程序共享会话【英文标题】:Sharing sessions across applications using the ASP.NET Session State Service 【发布时间】:2011-02-21 12:53:39 【问题描述】:

我正在尝试在托管在同一台服务器上的两个 Web 应用程序之间共享会话。一个是 .net 2.0 Web 表单应用程序,另一个是 .net 3.5 MVC2 应用程序。

两个应用程序的会话设置如下:

<sessionState
      mode="StateServer"
      stateConnectionString="tcpip=127.0.0.1:42424"
      />

在 webform 应用程序中,我将会话密钥发布到 MVC 应用程序:

protected void LinkButton1_Click(object sender, EventArgs e)

    Session["myvariable"] = "dan"; 
    string sessionKey = HttpContext.Current.Session.SessionID;

    //Followed by some code that posts sessionKey to the other application    

然后我在 MVC 应用程序中收到它并尝试使用相同的会话,如下所示:

[HttpPost]
public  void Recieve(string sessionKey )

    var manager = new SessionIDManager();

    bool redirected;
    bool IsAdded;

     manager.SaveSessionID(HttpContext.ApplicationInstance.Context, Id, out redirected, out IsAdded);
     var myVar = Session["myvariable"];


密钥正在发布,但会话似乎没有加载到 MVC 应用程序中,即 sessionKey 为空。我想做的事能做吗?

【问题讨论】:

你能把 Session id 发布到其他应用的代码贴出来吗 blogs.msdn.microsoft.com/toddca/2007/01/25/… @sotn 评论 (blogs.msdn.microsoft.com/toddca/2007/01/25/…) 中的链接显示了如何使 SQL 会话提供程序为所有应用程序返回相同的应用程序 ID,以便它们有效地共享相同的会话 【参考方案1】:

我是这样做的:

基本上,这两个应用程序都使用存储在 sqlserver 中的本机 .net sessionState。通过使用相同的机器密钥并对存储过程进行小幅调整——两个应用程序可以共享任何会话密钥和/或表单身份验证。

两个应用程序都会在其 web.config 中执行类似的操作:

<sessionState mode="SQLServer" sqlConnectionString="Data Source=.\SQLEXPRESS;User Id=test;Password=test;Application Name=AppName"  />
    <machineKey
validationKey="SOMEKEY"
validation="SHA1" decryption="AES"
/>

需要在数据库服务器上设置会话状态数据库,这两个应用程序都可以看到。

执行此操作的文档: http://msdn.microsoft.com/en-us/library/ms229862(VS.80).aspx

需要运行的命令: C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin>aspnet_regsql.exe -E -ssadd --sstype p -S .\SQLEXPRESS

存储过程 (TempGetAppID) 调整为:

 @appId int OUTPUT
AS

    -- start change

    -- Use the application name specified in the connection for the appname if specified
    -- This allows us to share session between sites just by making sure they have the
    -- the same application name in the connection string.
    DECLARE @connStrAppName nvarchar(50)
    SET @connStrAppName = APP_NAME()

    -- .NET SQLClient Data Provider is the default application name for .NET apps
    IF (@connStrAppName <> '.NET SQLClient Data Provider')
        SET @appName = @connStrAppName

    -- end change

SET @appName = LOWER(@appName)

【讨论】:

对于存储过程(假设您不需要更具可扩展性的解决方案),您可能只需硬编码应用名称:SET @appName = LOWER("MyAppNameHere") 生活没有那么完美。这个解决方案有一些错误。我已经开始使用它并注意到过时的会话行没有从数据库中删除。所以它非常增长,我得到异常“数据库'ASPState'的事务日志已满。”一段时间后。我该如何解决? 此外 ASPState_log.LDF 需要 ~50GB 8| 选择任务 -> 收缩 -> 数据库和 ALTER DATABASE [ASPState] SET RECOVERY SIMPLE GO 帮助了我。 @RredCat:通过在设置数据库时使用带有 -sstype p 参数的 aspnet_regsql.exe,他正在选择持久数据存储。关闭此参数,它将默认使用“tempdb”数据库。【参考方案2】:

问题在于会话密钥的范围仅限于应用程序,因此具有相同会话密钥的两个应用程序实际上具有不同的会话。

您可以做以下两件事之一:

    将两个应用程序作为虚拟目录放在一个通用 IIS 应用程序下。我认为这不是一个好主意,但它会起作用。

    为您要共享的数据推出您自己的会话数据解决方案。可能使用后端数据库作为公共存储,如果你有的话。

根据贾斯汀的评论,只是为了澄清选项 2 并不是指进程外会话的 SQL 状态管理。我的意思是让您实际手动管理两个会话的共享数据,可能使用数据库。

【讨论】:

我还打算建议将数据库用于会话管理解决方案。设置起来非常简单,但您可能会遇到相同的问题,不同的应用程序将具有不同的密钥并且无法共享数据。 @Justin,我并不是建议 OP 在 SQL Server 中使用 ASP.NET 会话。这肯定会有同样的问题,ASP.NET 中的会话密钥的范围是应用程序,而不管持久性如何。我的意思是 OP 应该完全“手动”管理共享数据的存储,并且如果需要,只对应用程序特定的会话数据使用 ASP.NET 会话机制。 @Dan,问题是您将两个应用程序混合到一个范围内。您现在不仅共享会话数据,而且将两个应用程序加载到同一个 appdomain 中,其中静态数据、应用程序变量、缓存变量都可能相互影响,只是因为您想共享会话数据。 @Chris Taylor - 如果我读到这个 ​​(blogs.msdn.microsoft.com/toddca/2007/01/25/…) 是对的,您可以通过一个简单的更改,修改 sql 会话提供程序以对所有应用程序使用相同的应用程序 ID,以便会话信息不再按应用程序限定。【参考方案3】:

您可以使用通用机器密钥在两个应用程序中为给定用户生成相同的会话 ID。此外,您还应该计划将两个应用程序的会话存储在公共存储中,例如 ASP.NET 状态服务或分布式缓存。

您可以使用 NCache 分布式缓存,它提供不同应用程序之间的会话共享功能。您在会话状态设置中为两个应用程序指定相同的应用程序 ID 标签,这允许您共享会话对象,前提是您为两个应用程序生成了相同的会话 ID。

【讨论】:

以上是关于使用 ASP.NET 会话状态服务跨应用程序共享会话的主要内容,如果未能解决你的问题,请参考以下文章

与 windows 服务共享 asp.net mvc 会话

如何在 ASP.NET 中跨多个 Web 应用程序维护相同的会话 ID

ASP.NET Session详解

扩展 ASP.NET 会话状态服务器

无法向会话状态服务器发出会话状态请求请。确保 ASP.NET State Service (ASP.NET 状态服务)已启动

ASP.Net Core Sql 会话持久化