</system.web>
1. Mode
模式设置允许你配置在请求间保存会话状态信息的会话状态提供程序。
Off :
禁用应用程序中所有页面的会话状态管理
InProc:
类似于传统 ASP 中保存会话的方式,它指示 ASP.NET 在当前应用程序域中保存信息。这种方式有最好的性能却具有最差的持久性,如果重启服务器,状态信息将丢失。InProc 是默认选项,它对于多数小型网站有意义,不过在 Web 集群中根本不能工作。你需要使用 SQL Server 状态服务才能使会话状态在服务器间共享。另一个不使用它的原因是它会产生较多的会话碎片。ASP.NET 应用程序会因为多种活动而回收,包括更改配置,更新页面,如果你发现你的应用程序域不断重启而导致会话过早丢失,你可以选择另一种更强健的会话状态提供程序。
使用进程外或 SQL Server状态服务时,请记住你需要考虑更多的问题:
- 使用 StateServer 或 SQLServer 模式时,要保存在会话状态中的对象必须是可序列化的,否则 ASP.NET 不能够将对象传送到状态服务器或保存到数据库中。
- 如果在集群中,则需要一些额外的配置以保证所有 Web 服务器同步,否则服务器会采用不同的方式编码会话状态信息,当用户由一台服务器路由到另一台服务器时会产生一个问题,解决该问题的办法是修改 machine.config 文件的 <machineKey>节以确保所有服务器使用相同的设置。
- 如果不使用进程内的状态提供程序,SessionStateModule.End 事件就不会触发,所有 global.asax或者HTTP模块中所有注册该事件的处理程序将被忽略。
StateServer:
采用该选项时 ASP.NET 使用一个独立的 Windows 服务来管理状态。即使该服务于 Web 服务器在同一台服务器上。它也会在 ASP.NET 主进程外加载,这样当 ASP.NET 进程需要重启时,可以为状态提供基本的保护。代价是两个进程间传递信息时将导致延迟,如果频繁访问和更改状态信息,则速度会明显变慢,让人无法忍受。
使用 StateServer 选项时,要为 StateConnectionString 设置一个值。该值定义了运行服务的计算机的 TCP/IP 地址和端口号。当然,在应用程序能够使用服务之前必须将其启动。
使用 StateServer 选项时还可以设置一个可选的 stateNetworkTimeout 特性,该特性指定放弃请求前等待服务器响应的最大秒数,默认值是 10 秒。
SQL Server:
该选项指示 ASP.NET 使用 sqlConnectionString 特性设定的 SQL Server 数据库保存会话信息。这是目前最具弹性同时也是目前最慢的状态存储方式,使用该模式需要一台装有 SQL Server 的服务器。设置 sqlConnectionString 时通常需要指定数据源(服务器地址),除非使用 SQL 整合安全方式,否则还要指定用户名和密码。此外,还需要安装临时会话数据库和一些特定的存储过程。其中存储过程负责保存和获取会话信息。
ASP.NET 使用命令行工具 aspnet_regsql.exe 实现这一目的。使用 aspnet_regsqt.exe 创建会话存储数据库时,要提供 -ssadd 参数,此外,使用 -S 参数表明数据库服务器的名称,-E 参数使用当前登录的 Windows 用户账户登录数据库。使用 -ssremove 参数可以移除 ASPState 数据库。
这个命令在当前计算机上创建会话存储数据库,使用默认的数据库名称 ASPState:
aspnet_regsql.exe -S localhost -E -ssadd
这个命令使用了假名 localhost ,它告诉 aspnet_regsql.exe 连接当前计算机上的数据库服务器,可以用数据库服务器所在的计算机名替代它。
标准会话状态超时时间也对 SQL Server 状态管理有效。因为 aspnet_regsql.exe 工具同时还创建了一个名为 ASPState_Job_DeleteExpiredSessions 的新 SQL Server 执行计划。只要 SQLServerAgent 服务在运行,这个执行计划每分钟执行一次。
此外,每次重启 SQL Server 时状态表会被删除,无论会话是否超时。这是因为此表是创建在 tempdb 数据库里,它是一个临时的存储区域。如果这不是你所期望的行为,你可以告诉 aspnet_regsql.exe 在 ASPState 数据库里安装持久状态表。这是可以使用参数 -sstype p(Persisted)
aspnet_regsql.exe -S localhost -E -ssadd -sstype p
现在,会话记录将保存在数据库里,即便重启了 SQL Server 也是如此。
最后一个选项是是创建一个非默认的状态表,这时使用参数 -sstype c(Custom),并通过 -d 参数提供数据库名称。
aspnet_regsql.exe -S localhost -E -ssadd -sstype c -d MyCustomStateDb
采用这种方法创建的是持久会话表。
如果使用了自定义数据库,还需要对 web.config 做两处微调:
<sessionState mode="SQLServer" allowCustomSqlDatabase="true" sqlConnectionString= "data source=localhost;Integrated Security=SSPI;Initial Catalog=MyCustomStateDb" />
Custom:
使用自定义模式时,需通过 customProvider 特性指定会话状态存储提供程序。这个特性指向 App_Code 文件夹中一个类的名字,或者在 Bin 目录或 GAC 中某个已编译的程序集的名字。创建自定义状态提供程序是一项需要小心处理的底层任务,需要保证安全性,稳定性和可扩展性,因此最好由可靠的第三方设计和测试。
2. 压缩
他可以减小序列化会话数据的大小。把 enableCompression 设置为 true 后,会话数据在传送到进程外会话状态存储时才起作用,因为这种情况下数据才会被序列化。
会话数据是使用 System.IO.Compression.GZipStream 类自动进行压缩的。
会话状态压缩最有意义的两个场景如下:
- 在内存里存储了大量会话状态数据时:Web服务器内存是非常珍贵的资源。理想情况下,会话状态用于少量的信息段,后端数据库处理大量数据的长期储存。但如果情况不是这样并且进程外状态服务器拥有大量的内存,压缩式潜在的解决方案。
- 在其他计算机存储会话状态数据时:在某些大型的 Web 应用程序中会话状态是在进程外的(一般是 SQL Server)并且在单独的计算机上。因此,ASP.NET 需要在网络连接上传送会话信息。显然,这样的设计降低了执行速度,不过,对于某些需要大量存储会话状态信息且流量非常大的网站而言,这仍然是最佳的折中方案。
第一种情况,压缩牺牲了 CPU 的时间换取了Web服务器内存。
第二种情况,压缩牺牲了 CPU 的时间节省了网络流量。
注:
实际的压缩量由于数据类型的不同差异很大,但在微软的测试中,客户端得到 30% 到 60% 的数据减少,在这些场景中它确保了性能的极大提升。
3. cookieless:
HttpCookieMode 枚举值:
UseCookies | 无论浏览器或设备是否禁用 cookie,总是可以使用 cookie(默认选项)。
如果设备不支持 cookie,后续的请求会话信息会丢失,因为每次请求都会获得新的标识符。 |
UseUri | 无论浏览器或设备是否支持 cookie,都不会使用 cookie。会话ID被存储在URL中。 |
UseDeviceProfile | ASP.NET 通过检查 BrowserCapabilities 对象来决定是否使用无 cookie 会话。
(只指明了设备应当支持的---而没有考虑用户可能禁用了浏览器中的 cookie) |
AutoDetect | ASP.NET 通过尝试设置和读取cookie(一种常用的 Web 技术)来确定浏览器是否支持 cookie
该技术可以正确判断浏览器是否支持 cookie 但却禁用了 cookie,在这种情况下,将使用无 cookie 会话。 |
使用无 cookie 模式时,例如下面这样:
<sessionState cookieless="UseUri" 。。。>
会话 ID 会自动插入到 URL 中,ASP.NET 获得请求时,它将移除 ID,检索会话集合,将请求送到相应的目录:
因为会话 ID 是插入到 URL 中的,所以相对链接也会自动获得会话 ID,真正限制无 cookie 会话状态的是:不能使用绝对链接,因为他们不包含会话 ID。
ASP.NET 默认允许重用会话标识。如果使用了一个含有过期会话的查询字符串,ASP.NET 会用这个 ID 重新创建一个会话。问题是某个会话 ID 会不经意的出现在某些公共场合,例如作为搜索引擎的查询结果。这样多个用户会使用同样的会话 ID 来访问服务器并加入到含有相同共享数据的相同会话中。为避免这一潜在的安全问题,使用无 cookie 会话时,推荐加入可选的 regenerateExpiredSessionId 特性,并把该值设为 true。这样当用户使用已经过期的会话 ID 时,会创建一个新的会话 ID。这么做的唯一缺点是,当前页面所有视图状态和表单数据将全部丢失,因为 ASP.NET 执行了一次重定向来保证浏览器使用新的会话 ID。
可以通过 Session 对象的 IsCookieless 属性来检查当前是否在使用无 cookie 的会话。
4. timeout
这个设置体现了会话状态最重要的折中。不同的分钟数会给服务器负载及应用程序性能带来非常大的影响。理想状态下,最佳的时间应当足够短,保证服务器内存能及时释放,同时这个时间也应该足够长,保证客户端在暂停一段时间后会话不会丢失还能继续使用。
可以在代码中设置:
Session.Timeout = 10;
会话状态安全 会话状态中的信息非常安全,因为它们只保存在服务器上。然而含有会话 ID 的 cookie 可能很容易被篡改。就是说一个恶意用户可以偷走 cookie 然后在另一台计算机上继续使用。
一个常用的方法是使用自定义的会话模块来检查客户端 IP 地址的变化。唯一真正有效的方法是仅在使用了 SSL 的网站上使用会话 cookie。采用这种方法,会话 cookie 被加密从而在其他计算机上不可用。如果使用这种方式,将会话 cookie 标识为安全 cookie 才有意义,这样 cookie 只能通过 SSL 连接传送。这使得用户不能将 URL 由 https:// 修改为可以不使用 SSL 发送 cookie 的 http:// 。
Request.Cookies["ASP.NET_SessionId"].Secure = true; // 这样的 cookie 必须在使用了 SSL 的网站上传送
这条代码应在用户通过验证后立即使用,另外还要确保会话状态中至少有一点信息,这样它才不被取消。