关于session的共享要分一下几种情况来分析:
1.用asp.net 开发的同一个系统部署到多个服务器上时,实现各服务器之间的session共享。
2..用asp.net 开发的多个系统部署到一个或多个服务器上时,实现session共享 。
3.用asp.net开发的系统和用其他语言开发的系统部署到一个或多个服务器上时,实现session共享。
要解决上面这些问题,首先要了解.net下是如何处理session的。
一. .net 中session 的处理分析
1.关于Session,SessionID和Cookies
Session数据保存在服务器端, 但是每一个客户端都需要保存一个SessionID, SessionID保存在Cookies中, 关闭浏览器时过期.在向服务器发送的HTTP请求中会包含SessionID, 服务器端根据SessionID获取获取此用户的Session信息.很多初级开发人员不知道SessionID和Cookies的关系, 所以常常认为两者没有联系. 这是不正确的. 因为SessionID保存在Cookies中的,使用Request.Cookies["ASP.NET_SessionId"]就能取得当前的SessionID.而不同的网站之间相同键值的cookies是以域来区分的,如果对cookiesi的写入作下修改就能使各网站共享SessionID,列如:
protected void Session_Start(object sender, EventArgs e)
{
Response.Cookies["ASP.net_SessionId"].Value = Session.SessionID.ToString();
Response.Cookies["ASP.net_SessionId"].Domain = ".local.com";
}
2.Seission的存储方式
.NET提供了5种保存Seission的方式:
方式名称 | 存储方式 | 性能 |
Off | 设置为不使用Session功能 | 无 |
InProc | 设置为将Session存储在进程内,就是ASP中的存储方式,这是默认值。 | 性能最高 |
StateServer | 设置为将Session存储在独立的状态服务中。通常是aspnet_state.exe进程. | 性能损失10-15% |
SQLServer | 设置将Session存储在SQL Server中。 | 性能损失10-20% |
Customer | 自定制的存储方案 | 由实现方式确定 |
我们可以在Web.Config中配置程序使用的Session存储方式.默认情况下是InProc, 即保存在IIS进程中. 关于Off, InProc和Customer本文不做讲解. 相关文章大家都可以在网上搜索到.
3.使用 StateServer 模式搭建Session服务器
(1)服务器端配置
1.启动 Asp.net State service服务.(这个服务默认的状态为手动.修改为自动并启动.)
2.修改注册表: [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\aspnet_state\Parameters]
设置 AllowRemoteConnection = 1 , 设置 Port = 42424 (十进制,默认即为42424)
Port是服务的端口号
AllowRemoteConnection 表示是否允许其他机器连接,0为仅能本机使用,1为可以供其他机器使用.
(2)客户端设置
在Web应用程序的Web.Config中, 我们需要修改 <configuration> / <system.web> 的<sessionState>节点.如果没有
没有则添加(默认使用的是InProc方式)
<sessionState
mode="StateServer"
stateConnectionString="tcpip=服务器ip:42424"
cookieless="false"
timeout="60"/>
上面的参数我们可以根据需要修改.
4.使用SqlServer模式搭建Session服务器
(1)服务器端配置
a.使用SQL文件创建Session数据库
在ASP.NET 1.0和1.1 版本中, 只能使用这种方式.对于2.0及其以上版本,请使用aspnet_regsql.exe工具.(当然此方法也通用2.0版本)
.net提供了数据库安装脚本,可以在机器的windows文件夹中找到:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ InstallSqlState.sql
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ InstallSqlStateTemplate.sql
根据ASP.NET的版本不同, 需要使用不同的SQL脚本. ASP.NET主要有1.1和2.0两个版本,可以在不同的版本文件夹找到这两个SQL.
InstallSqlState.sql 是创建默认名称的数据库"[ASPState]".此SQL可以直接运行.
InstallSqlStateTemplate.sql 可以使用自己指定的数据库保存数据.此SQL需要自己修改后运行, 打开SQL文件将其中 [DatabaseNamePlaceHolder] 替换为自己指定的数据库名称.
执行instabllsqlstate.sql时不需要指定数据库,可以在任意数据库上执行.此SQL会自己创建新的数据库
b.使用aspnet_regsql.exe工具
ASP.NET 2.0版本后微软提供了aspnet_regsql.exe工具可以方便的配置Session数据库.该工具位于 Web 服务器上的"系统根目录\Microsoft.NET\Framework\版本号"文件夹中.
使用举例:
aspnet_regsql.exe -S . -U sa -P 123456 -ssadd -sstype p
-S参数:
表示数据库实例名称. 可以用"."表示本机.
-U和-P参数:
表示用户名和密码.
-E参数:
可以再-U –P 与 -E中选择一组. –E表示以当前系统用户通过windows身份验证登录数据库, -U -P则是使用SqlServer用户登录数据库.
-ssadd / –ssremove 参数:
-ssadd表示是添加Session数据库, -ssremove表示移除Session数据库.
sstype 参数:
选项 | 说明 |
t | 将会话数据存储到 SQL Server tempdb 数据库中。这是默认设置。如果将会话数据存储到 tempdb 数据库中,则在重新启动 SQL Server 时将丢失会话数据。 |
p | 将会话数据存储到 ASPState 数据库中,而不是存储到 tempdb 数据库中。 |
c | 将会话数据存储到自定义数据库中。如果指定 c 选项,则还必须使用 -d 选项包括自定义数据库的名称。 |
(2)Session客户端设置
此房是同样需要Web应用程序修改Web.Config中的<sessionState>节点.如果使用默认的数据库(ASPState库), 则配置如下:
<sessionState
mode="SQLServer"
sqlConnectionString="server=192.168.9.151; uid=sa; pwd=123456;"
/>
如果使用了自定义的数据库名称,则还需要制定allowCustomSqlDatabase属性并在数据库连接串中指定数据库:
<sessionState
mode="SQLServer"
allowCustomSqlDatabase="true"
sqlConnectionString="server=192.168.9.151; DataBase=MyAspState;uid=sa; pwd=123456;"
/>
理解了.net下session的处理方式之后,对于session的共享问题就会有解决的思路了。对于1和2两种情况,只需要采用sqlserver存储session并修改sessionId的cookie域,基本上就能解决了。对于第3种情况,就有点麻烦,一种方式是采用sqlserver存储session,在用其他语言编写的系统中,需要根据sessionId从数据库中读取相应的数据并现实反序列化。另外一种方式是实现session的自定制的存储方案。
另外需要注意一下几点:
1.SqlServer模式存储:
(1) 要保存在Session中的对象是可序列化的。
(2.)如果使用了默认是数据库, 则在客户端配置文件中的数据库链接字符串的用户,需要拥有ASPState和tempdb两个库的dbowner权限.
(3.)在SQLServer模式下,session过期是由SQL Agent使用一个注册任务完成的,要确认SQL Agent已经运行。否则无法清理过期的Session数据, 会导致数据库数据一直增加.
(4)如果使用SqlServer模式时, 对于Web场中的各服务器的 ASP.NET 应用程序路径必须是相同的。请在 IIS 配置数据库中对 Web 场中的所有 Web 服务器进行 Web 站点的应用程序路径同步。大小写一定要相同,因为 Web 站点的应用程序路径是区分大小写的。
(5)需要让所有机器的MachineKey相同.在Machine.Config中配置:
<machineKey validationKey="1234567890123456789012345678901234567890AAAAAAAAAA" decryptionKey="123456789012345678901234567890123456789012345678" validation="SHA1" decryption="Auto" />
(6)一般在Session超时或删除之后,SessionID保持不变. 因为Session过期后会在服务器端清除数据, 但是SessionID保存在用户浏览器上, 所以只要浏览器不关闭则HTTP头中的SessionID保持不变.
(7)关闭浏览器后再访问, SessionID会不同.
(8)每打开一个IE6窗口, SessionID都不同, 在IE6中两个窗口的Session不能共享.
(9)FireFox的标签页和新的FireFox窗口, SessionID都相同, 在FF的窗口和标签页上Session能共享.
(10)对于包含FrameSet的页面,比如:
<frameset cols="25%,50%,25%"> <frame src="SessionID.aspx"> <frame src="SessionID.aspx"> <frame src="SessionID.aspx"> </frameset>
如果后缀名是.htm并且.htm文件没有交给ASP.NET的ISAPI处理, 那么根据服务器速度在每个Frame页面生成不同的SessionID, 再刷新后相同都等于最后一个SessionID.
解决办法是将.htm后缀改成.aspx, 或者将.htm文件交给ASP.NET的ISAPI处理.