如何将Sessionstate存储在托管.NET MVC网站的数据库中

本文关键字:MVC NET 网站 数据库 Sessionstate 存储 | 更新日期: 2023-09-27 17:59:33

我在托管MVC 4网站上遇到用户会话超时问题。当我使用IIS Express在本地运行网站时,我会有很长的超时时间。一旦网站发布到主机(GoDaddy)上,登录的超时时间就会降到非常短(约10-15分钟)。

我正在使用表单身份验证。登录时我使用标准:

FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);

然后在我的控制器中,我使用Authorize属性:

[Authorize]
public class BillingAccountController : Controller { ... }

我已经尝试了几种涉及更改web.config中设置的解决方案。在这一点上,我有以下几行来延长超时时间:

<configuration>
  ...
  <system.web>
    ...
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880" cookieless="UseCookies" />
    </authentication>
    ...
    <sessionState mode="InProc" cookieless="UseCookies" timeout="2880" />
  ...
  </system.web>
  ...
</configuration>

但这并不奏效。它似乎被主持人忽视了。

我见过一些改变IIS7设置的解决方案,但由于这是托管的,我认为我无法访问它。(我查看了我的GoDaddy面板,虽然有IIS菜单,但它非常有限。)

该网站已上线约4个月,这是客户持续不断的投诉。

如果有帮助的话,我正在使用自定义的角色和成员资格提供程序。我只使用Forms Auth来创建和授权Auth cookie。此时,我可能对另一个登录解决方案持开放态度。比如如果必须放弃表单身份验证。

我可以想象一些解决方案,比如创建我自己的带有自定义属性的cookie,或者某种以某种方式扩展会话的定期AJAX调用,或者放弃cookie并使用数据库,搜索第三方解决方案,等等,。。。。

客户希望我做一些事情——引用——"永远"不会忘记。我不确定这个答案是否正确。但如果我至少能在一到两个小时的不活动后让它超时,我想他们会很高兴,因为这种10-15的超时真的很烦人。

底线问题是:如何延长会话/登录超时,如果由于主机原因无法延长,最好的解决方法是什么?

更新

在阅读了@DouglasThomas在他的回答中提供的资源后,我更新了web.config,改为使用SQLServer会话:

<sessionState mode="SQLServer" sqlConnectionString="ConnSessionState" sqlCommandTimeout="30" cookieless="false" timeout="1440" />

使用连接字符串:

<add name="ConnSessionState" connectionString="data source=1.1.1.1,1433;user id=userid;password=**************" providerName="System.Data.SqlClient" />

这似乎并没有解决问题。在不到20分钟的时间内,用户登录仍处于超时状态。不过,我确实有一个问题:SQLServer会话是否需要在SQL数据库端进行任何配置?或者只是web.config的更改?我读到的文件不清楚。

更新2

根据@DaveA的建议,我已经更新了我的解决方案。但它似乎仍然不起作用。我已经用asp会话状态数据库配置了SQL Server Express。我使用此Microsoft文档作为指南,首先重新配置服务器设置(SQL Express的要求),然后使用以下命令行:

aspnet_regsql.exe -ssadd -sstype p -S SERVERPC'SQLEXPRESS -E

以在CCD_ 3数据库中创建会话状态数据库。新数据库已成功创建,其中包含多个表和多个存储过程。然后,我在web.config中更新了sessionState节点,如下所示:

<sessionState 
  mode="SQLServer"
  sqlConnectionString="data source=1.1.1.1,1433;user id=userid;password=**************" 
  allowCustomSqlDatabase="true"
  sqlCommandTimeout="30"
  cookieless="false"
  timeout="1440"
  />

但它似乎对登录的持续时间没有任何影响。我甚至无法判断它是否正在连接到数据库,因为ASPState数据库中的表中没有新记录。我将注意到,我并没有在web应用程序的任何位置显式地使用会话变量。我假设表单身份验证应该以某种方式使用它们。

解决方案

在与@DaveA共同努力后,他在www.asp.net论坛上发现了一篇关于有人也有同样问题的文章:http://forums.asp.net/t/1967093.aspx?Forms+身份验证+会话+超时+问题+10分钟后

根据@DaveA的建议,我在web.config中添加了一个machineKey部分(我从这里生成)。在直播网站上上传和测试后,在20多个小时的不活动后,用户登录仍然存在。所以我相信机器钥匙就是我的答案。

如何将Sessionstate存储在托管.NET MVC网站的数据库中

问题是:

您正试图将已定义的连接字符串与SessionState提供程序一起使用。这是非常合乎逻辑的,但不起作用,因为SessionState提供程序仍然使用ASP.NET 1.0中的原始定义,而连接字符串是在ASP.NET 2.0中引入的。

这是微软从未解决过的一个奇怪的矛盾。

为了设置DBSession状态:

1)定义SessionState时使用完整的连接字符串

<sessionState mode="SQLServer" 
    sqlConnectionString="data source=1.1.1.1,1433;user id=userid;password=**************" 
    sqlCommandTimeout="30" cookieless="true" timeout="1440" />

非常重要:设置cookieless="true",并在登录方法中确保rememberme=false。这些步骤对于防止框架将cookie用于会话状态非常重要。

2)在sql server上创建架构:

aspnet_regsql.exe -ssadd -d <Your Database> 
           -sstype c -S <Server> -U <Username> -P <Password>

3)web.config中设置机器密钥属性以将您的会话和成员身份绑定到主机:

跨虚拟目录的表单身份验证

http://aspnetresources.com/tools/machineKey


请记住:

使用数据库进行会话的性能成本很高,而且(正如您所注意到的)所有参数传递在功能上都很乏味。这远不是一个完美的解决方案。

由于负载平衡,共享帐户通常会导致会话出现问题。在这种情况下,您最好使用Cookie。更大的问题似乎是GoDaddy出于安全原因限制会话超时(Cookie和会话)的共享托管策略。

如果性能出现问题,您可能需要更改托管计划。


机器密钥:用于将成员身份绑定到域。当机器密钥匹配时,可以在多个域之间共享成员身份。即使没有DB会话,这也可能产生影响(值得一试)。