ASP.NET 3.5核心编程学习笔记(35):会话状态的自定义管理

  综合各方面考虑,有3种会话状态管理的自定义方案:

  1. 保留默认的会话模块,但编写自定义的状态提供程序来更改存储介质。这样,我们还有机会重写一些用于在存储与Session之间运载会话数据的辅助类。

  2. 保留默认的会话模块,但替换会话ID生成器。

  3. 将默认的会话状态模块替换成自己的。这种方法提供了最好的灵活性,但也最为复杂,建议仅当的确必要且知道确切的实现方法才使用这种方案。

构建自定的会话状态提供程序

  会话状态提供程序是一种组件,负责为当前会话数据进行服务。当请求需要状态信息时,该组件便会被调用,从给定的存储介质中获取数据,并返回给主调模块。在请求结束时,也会被调用,以便将提供的数据写入存储层。

  ASP.NET支持三种状态提供程序,下表对其作了说明:

2011042423174521.gif

  我们还可以编写自己的状态提供程序类,使其应用自选的存储介质。

定义会话状态存储

  状态提供程序是一种继承于SessionStateStoreProviderBase的类,下表列出了其接口的主要方法:

2011042423205481.gif

2011042423224980.gif

  继承SessionStateStoreProviderBase类,并保留默认的ASP.NET会话状态模块,这种方案只能更改会话状态数据存储和数据恢复这部分功能,其他功能不能更改。

锁定与过期

  状态提供程序必须实现会话连续访问的锁定机制。会话状态模块能够判断请求需要的是会话状态的只读访问还是可读/写访问,根据判断结果,它会调用GetItem或GetItemExclusive。在这两个方法的实现中,提供程序的编写者应创建读取会话/写入会话的锁定机制,允许多个并发的读取操作,但要阻止向已锁定的会话写入数据。

  另一个问题是,要使会话状态模块知道给定会话的过期时间。若global.asax定义了Session_End事件的处理程序,会话状态模块会调用SetItemExpireCallback。通过该方法,状态提供程序会得到一个回调函数,其原型如下:

 
  
public delegate void SessionStateItemExpireCallback( string sessionID, SessionStateStoreData item);

  会话模块要将返回的委托在内部存储,在给定会话超时时调用。对过期回调的支持是可选的,事实上,只有InProc真正支持它。如果不希望自定义提供程序支持过期回调,应指示SetItemExpireCallback方法返回false。

  如果要支持无Cookie会话的提供程序,还必须实现CreateUninitialized方法,以便向数据存储中写入空的会话项。确切地讲,空的会话项是一种完整的数据项,但不包含实际的数据。也就是说,会话项应包含会话ID和创建时间(可能还包含锁的ID),但不包含数据。对于ASP.NET 2.0,在无Cookie模式下,只要在会话过期后发出请求,就会生成新的ID。会话状态模式会生成新的ID,并使浏览器重定向。若未初始化的会话项没有被分配新的ID,那么新的请求仍会被看作是过期会话中的请求。

会话数据字典的替换

  SessionStateStoreData是代表会话项的类(一种包含与会话有关的所有数据的数据结构)。事实上,GetItem和GetItemExclusive返回的就是该类的实例。该类有3个属性:Items、StaticObjects和Tiemout。

  Items最终用于为页面对象Session属性中的键/值集合提供数据。StaticObjects中包含的是隶属于当前会话的静态对象(如在global.asax中声明,且在会话范围中可见的对象)。Timeout是会话状态的有效时间(以分为单位),默认值得为20分钟。

  一旦会话状态模块为请求获得会话状态,该模块会将Items集合的内容写入HttpSessionStateContainer类的新实例。该对象之后被传给HttpSessionState类的构造函数,成为Session属性幕后的数据容器。

  对于会话模块和状态提供程序来说,会话项的容器只不过是实现ISessionStateItemCollection接口的类。默认情况下,实例使用的类为SessionStateItemCollection。只要自定义的类实现了上述接口,就可以替代SessionStateItemCollection类。

  若要编写状态提供程序,SessionStateUtility类会非常有用,该类包含序列化和反序列化会话项的方法,以便将其存储到某介质中,或将其读出。此外,该类还有有些方法,可以从会话中抽取数据字典并将其添加到HTTP上下文和Session属性。

自定义会话状态提供程序的注册

  为使应用程序能够使用自定义的会话状态提供程序,我们需要在web.config文件中注册它。假设有一个叫SampleSessionStaeProvider的提供程序类,被编译为MyLib程序集:

 
  
< system .web >
< sessionState mode ="Custom"
customProvider
="SampleSessionProvider" >
< providers >
< add name ="SampleSessionProvider"
type
="SampleSessionStateProvider, MyLib" />
</ providers >
</ sessionState >
</ system.web >

自定义会话ID的生成

  为生成会话ID,ASP.NET 2.0使用了名为SessionIDManager的组件。该类既不是HTTP模块也不是提供程序,它只是一个继承于System.Object且实现ISessionIDManager接口的类。只要实现ISessionIDManager接口,自定义的类就可以替换该组件。

默认的行为

  默认的会话ID模块以字节数组的形式生成会话ID,并带有15个值的强随机序列进行加密。该数据之后会被编码为包含24个字符的字符串,且每个字符都符合URL的标准,系统会将其用途会话ID。

  会话ID可通过HTTP Cookie或修改的URL在服务器与客户端间传输,具体方式取决于<sessionState>中cookieless属性的值。注意,若使用无cookie会话,会话ID模块要负责将ID添加到URL中,并对浏览器进行重定向。默认的生成器会将浏览器重定向到下面的虚URL:

  http://www.contoso.com/test/(S(session_id))/page.aspx

  这种URL发出的请求如何被正确处理呢?在无Cookie会话情况下,会话ID模块会利用一个轻型的ISAPI筛选器(aspnet_filter.dll)将传入的URL动态重写为实现资源的URL。请求会被正确处理,但地址栏中的路径不会改变。检测到的会话ID会被置于一个叫AspFilterSessionId的标头中。

自制的会话ID管理器

  会话ID管理器是一个实现ISessionIDManager接口的类,因而我们有两种方案来构建它:

  1. 新建一个类,并使其实现该接口。

  2. 从SessionIDManager派生出一个类,并重写其中的两个虚方法(CreateSessionID和Validate),以实现某些特殊的逻辑。

  ISessionIDManager接口的方法见下表:

2011042500015656.gif

  如果打算使用完全自定义的会话ID生成器,应注意以下几点:

  1. 生成ID的算法非常关键。如果不实现强随机加密过程,当某些会话处于活动状态时,恶意用户可能会猜到有效的ID。为此,生成全局唯标识符(GUID)是一个不错的选择。

  2. 我们可以选择是否支持无Cookie的会话。如果添加这种支持,则必须使该组件能从HTTP请求中抽取会话ID,并对浏览器进行重定向。为此,可能需要ISAPI筛选器或HTTP模块,对请求进行预处理并对其做适当的修改。

  创建好会话ID模块后,便可将其在配置文件中注册:

 
  
< sessionState sessionIDManagerType ="Samples.MyIDManager, MyLib" >
</ sessionState >

转载于:https://www.cnblogs.com/free722/archive/2011/04/25/2026599.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值