将Session存入SQLServer实现夸站点访问

本文详细介绍了如何通过将Session存储在SQLServer中,实现多个ASP.NET站点之间的会话共享。关键在于理解ASPStateTempSessions表的结构,并通过调整AppName或共享Cookie来确保不同站点能使用相同的SessionID。配置Web.config的sessionState节点,设置相同的数据库连接和忽略AppName,或者通过设置Cookie的Domain属性,都能实现这一目标。同时,文中还提到了定期清理过期Session的作业ASPState_Job_DeleteExpiredSessions的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(1)建立存放 Session 的 DataBase
打开Visual Studio 命令提示工具执行下面的命令,此命令会创建存储Session的数据库ASPState、清除过期Session的作业,以及相应的一些存储过程。
D:/Microsoft Visual Studio 9.0/VC>aspnet_regsql -S 192.168.4.188 -U sa -P dianji
an@2010 -ssadd -sstype p

会话数据保存在指定的SQLServer数据库中,会话数据通过SessionID进行查找,理论上只需要使多个站点共享同一会话数据库即可共享会 话数据,确定了思路便好办。多个站点共享统一会话数据库在.NET下是很容易的事情,只需要在WEB.CONFIG里配置sessionState节点指 定会话存储模式以及相同的会话数据库即可。事情没有这么简单,不同的站点其SessionID是不同的,就算SessionID相同了,保存在会话数据库 中的实际SessionID的值也不只是网站生成的SessionID,而是在SessionID后加上了站点的AppName,因此即使各个站点共享了 会话数据库也不能共享会话数据。打开会话数据表ASPStateTempSessions中的记录,可以发现如下几个数据

ASPStateTempSessions各个字段的意义如下:

表1 ASPStateTempSessions表

类 型

描 述

SessionId

char(88)

索引字段,它表示会话ID

Created

DateTime

指出会话被创建的时间。默认值为当前时间

Expires

DateTime

指出会话将到期的时间。该值一般等于会话状态的创建时间加上Timeout中指定的分钟数。注意,Created指会话的创建时间,而 Expires把分钟数加到第一个数据项被添加到会话状态的时间

LockDate

DateTime

指出会话被锁定以添加最后一个数据项的时间。该值表示为当前的UTC(Universal Time Coordinate)时间

LockDateLocal

DateTime

与LockDate一样,但是它只表示系统的本地时间。ASP.NET 1.x不支持该列

LockCookie

int

指出该会话被锁定的次数——即,访问次数

Timeout

int

指出会话的超时时间(以分为单位)

Locked

bit

指出会话当前没有被锁定

SessionItemShort

VarBinary(7000)

可以取null的字段。它表示指定会话中的值。这些字节的布局等同于StateServer提供程序所述的布局。如果对字典进行序列化需要7000 多字节,则使用SessionItemLong

SessionItemLong

Image

可以取null的字段,表示一个超过7000字节的会话状态的序列化版本

Flags

Int

指示SessionStateActions枚举类型的行动标记(初始化数据项)。ASP.NET 1.x不支持该列




其中的SessionId包括两个部分:网站生成的24位SessionID及8位 AppName(这个AppName是怎么来的呢?)对于不同的站点,其AppName不同,在能够在不同站点下使24位SessionID相同的情况 下,要保证经过组合加上AppName后的SessionID相同,可以通过修改存储过程TempGetAppID,使其得到的SessionID与 AppName无关,修改TempGetAppID如下:
 1
 2      CREATE   PROCEDURE  dbo.TempGetAppID
 3      @appName     tAppName,
 4      @appId        int  OUTPUT
 5      AS
 6      SET   @appName   =   LOWER ( @appName )
 7      SET   @appId   =   NULL
 8
 9      SELECT   @appId   =  AppId
10      FROM   [ JSEC_SessionDB ] .dbo.ASPStateTempApplications
11     --  WHERE AppName = @appName   //屏蔽该行
12
13      IF   @appId   IS   NULL   BEGIN
14          BEGIN   TRAN         
15
16          SELECT   @appId   =  AppId
17          FROM   [ JSEC_SessionDB ] .dbo.ASPStateTempApplications  WITH  (TABLOCKX)
18          WHERE  AppName  =   @appName
19         
20          IF   @appId   IS   NULL
21          BEGIN
22              EXEC  GetHashCode  @appName @appId  OUTPUT
23             
24              INSERT   [ JSEC_SessionDB ] .dbo.ASPStateTempApplications
25              VALUES
26             ( @appId @appName )
27             
28              IF   @@ERROR   =   2627  
29              BEGIN
30                  DECLARE   @dupApp  tAppName
31             
32                  SELECT   @dupApp   =   RTRIM (AppName)
33                  FROM   [ JSEC_SessionDB ] .dbo.ASPStateTempApplications 
34                  WHERE  AppId  =   @appId
35                 
36                  RAISERROR ( ' SQL session state fatal error: hash-code collision between applications  '' %s ''  and  '' %s '' . Please rename the 1st application to resolve the problem. '
37                              18 1 @appName @dupApp )
38              END
39          END
40
41          COMMIT
42      END
43
44      RETURN   0
45 GO
46


经过以上修改之后,下面要实现多个站点共用同一个SessionID,对 ASP.NET的会话模型System.Web.SessionState.SessionIDManager.GetSessionID(HttpContext context)方法进行反编译,分析其源代码:

 1   public   string  GetSessionID(HttpContext context)
 2   {
 3        string  id  =   null ;
 4        this .CheckInitializeRequestCalled(context);
 5        if  ( this .UseCookieless(context))
 6       {
 7            return  ( string ) context.Items[ " AspCookielessSession " ];
 8       }
 9       HttpCookie cookie  =  context.Request.Cookies[Config.CookieName];
10        if  ((cookie  !=   null &&  (cookie.Value  !=   null ))
11       {
12           id  =   this .Decode(cookie.Value);
13            if  ((id  !=   null &&   ! this .ValidateInternal(id,  false ))
14           {
15               id  =   null ;
16           }
17       }
18        return  id;
19   }
20  
21    
22  


可 以看到,SessionID是通过客户端的Cookie进行保存的,因此,只要使各个站点共用同一个Cookie文件保存SessionID即可达到目 的。如何使不同的站点共用同一个Cookie呢?只要设置cookie.Domain为相同的域即可。在页面的PageLoad事件中加上以下代码:

1           HttpCookie cookie  =  HttpContext.Current.Request.Cookies[ " ASP.NET_SessionId " ];  //"ASP.NET_SessionId"是ASP.NET会话模型中默认的SessionId变量名称
2           cookie.Domain = ".websitename.com";
3           cookie.Expires  =  DateTime.Now.AddDays( 365 ); //设置Cookie保存的天数,不可少于1天
4           HttpContext.Current.Response.Cookies.Add(cookie);


经过以上步骤之后,终于真正的实现了多站点会话共享。 

 

二.

和上面前面一样.在WEB.CONFIG里配置sessionState节点指定会话存储模式以及相同的会话数据库.由上面第一种方法分析可以知 道.AppName不一样.上面是让它忽略AppName.下面就是让他AppName一样.这样也能达到同样效果.具体做法是:

在每个子站点必须设置相同路径主目录(比如.有三台服务器.WEB程序IIS主目录都应指向同一位置.如都在D:/WebRoot下)

这样.AppName会得一个相同的值.

注意 :如果你是在已经建立好的IIS站点上.采用这种模式.建议选删除原来的 WEB站点.再新建成每台都一样的物理路径的IIS站点.我的理解是.一但建立就生成了AppName.以后修改它是不会变的(不知道是不是这个原因,但 我就是这样才解决的.删除其它已建立好的.重新建立的),所以保证真正的AppName一样.得严格按照上面的做法.

 

(2)设置 Web.config 内容
打开 Web.config → 找到 <sessionState> 节点内容 → 修改为以下内容即可:
<sessionState mode="SQLServer" sqlConnectionString ="data source=192.168.0.2; user id= sa; password=123456" timeout="20" />

 

(3)开启作业ASPState_Job_DeleteExpiredSessions,及时的清空过期Session

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值