越深入的了解asp.net,就会非常的感叹它的设计,功能强大,任何阶段的开发人员,不管是菜鸟、大牛,都能找到自己的用武之地:灵活,即可以利用本身提供程序通过配置加简单代码方便的完成需求,也可以充分利用它的扩展性完成一些特定或本身不具备的功能。我们可以从session的设计中看到一些这样的例子。
准确的来说是会话状态,它是服务状态管理的一部分,每个访问应用程序的客户端有不同的会话且包含不同的信息,我们可以通过属性session来访问它。与viewstate存储方式不同的是,它把信息存储在服务器,当用户访问多时,可能会给服务器带来不小的压力。
既然session的数据存储在服务器,这就涉及到服务端要识别客户端的问题。asp.net使用一个标识来跟踪会话,我们可以session实例的SessionID的属性来获取这个标识,你可以通过配置来决定这个标识是通过cookie或url的方式传递,这个标识是一个私有的算法来生成的一个120位的值,它能保证唯一且随机,保证各个客户端不会出现相同的标识且不会被其它人通过其它方式生成。服务器端获取到这个ID,就会查找相应的会话,如果能找到相应的数据,就会把它填充到session中,供我们使用。另外还有一点要注意的是,如果你还没有用session存储信息,那么每次新请求,asp.net就会生成一个新的ID。
那么这整个的流程,又是asp.net的那个模块来负责的呢?我们知道每个http请求都会经过多个模块的处理管道,其中有一个叫做SessionStateModule的模块,它负责产生会话ID,从session提供程序中获取数据,并绑定到请求的上下文中。当请求处理完毕时,它还负责保存会话信息到session提供程序中。
这个session提供程序是什么?对,就是我们配置中sessionState mode中所指出的InProc,StateServer,SqlServer,我们可以根据需求很简单通过配置来实现会话信息存储在当前应用程序进程内、独立的服务或数据库中。但其实这个提供程序要求是一个实现了IHttpSessionState的任意类,以上的三种只不过asp.net内置的三种经常会用到的提供程序而已,如果我们有特殊需求时,我们完全可以自己定义提供程序。还有另一个极端,不使用会话状态。mode中还有另外两个值:Custom,Off。
我们前文中说到的session存储到服务器端的,如果大量用户访问时,这对服务器的内存是一个不小的压力;还有如果使用的其它计算机存储会话信息,这其中涉及到数据的网络传输。这些情况下,通过设置enableCompression=true启用压缩来减小数据的大小,会是一个较好的选择。但是要注意的,虽然省了内存或网络传输流量和时间,但是数据的压缩和解压缩都是需要耗费额外的cpu时间的。究竟如何取舍,这就要看实际的情况了。
session把信息存储到服务器端,整个过程中唯一发送到客户端的只有一个session的ID,唯一的突破点就在于黑客入侵用户的电脑,并且复制用户cookie在另一个电脑使用,从而达到以一个用户身份来访问应用程序,即使这种情况,就算你把用户私密如信用卡的账号、密码存储到session中,只要你只是用它来进行和用户输入的进行校验,而不是2的把它输出的页面或客户端,黑客是没办法获取到这些session信息的。但是这始终是一个隐患,用户的一些信息可能会泄露,这样我们可以使用自定义会话模块来检测cookie和用户IP或其它客户端特定信息来检测是否同一个用户的请求,更有效的方法启用SSL,这样cookie被加密只能在此计算机使用,并且启用Request.Cookies[“Assp.NET_SessionId”].Secure=true,这样cookie只能通过SSL即URL的Https://传递。
另外对于使用无cookie的会话,尽管这个ID是加密过的,但是还是可以通过一个含有有效会话ID的Url来加入这个会话,对于此方法启用SSL也无法杜绝其它用户,但是我们可以通过启用regenerateExpiredSessionId=true,这样可以让过期的ID失效,减少攻击的机率。
本文没有对session的细节使用做太多的说明,只是希望能从session的设计中学习一些设计的思路,可以用于自己应用的开发当中,然后对session实际的应用使用何种提供程序有个取舍,其它一些细节都会迎刃而解,最后使用任何中机制都不要忘了安全性。