标识符。如果同一Web应用在“Web农场”(Web farm)的多台服务器上运行,则必须存在这样一种机制:保证来自同一用户的请求总是被定向到处理该用户第一次请求的服务器。
三、伪会话管理机制
如前所述,基于Cookie的会话管理技术面临着种种问题。下面我们要设计一种新的会话管理机制来解决这些问题。这种会话管理机制称为“伪会话”(Pseudo Session)机制,它具有如下特点:
· 对象和数据不是保存在内存中,而是以文本文件形式保存。每一个文本文件与一个特定的用户关联,文件的名字就是会话的标识符。因此,文件名字必须是唯一的。
· 文本文件保存在一个专用的目录中,所有Web服务器都可以访问这个目录。因此,伪会话可以用于Web农场。
· 会话标识符不作为Cookie发送,而是直接编码到URL里面。因此,采用伪会话技术要求修改所有的超级
链接,包括HTML表单的ACTION属性。
此外,实现伪会话管理机制时我们还要考虑到以下几点:
· 它应该与应用无关,其他想要实现同样功能的开发者应该能够方便地重用它。
· 考虑到安全原因,应该有一种为会话标识符生成随机数字的办法。
· 为了作废过期的会话,应该设定一个超时值。同一个用户,如果他超过一定的时间之后再次返回,他将获得一个新的会话标识符。此举能够防止未经授权的用户冒用其他人的会话。
· 应该有一种收集过期会话并删除相应文本文件的机制。
· 如果用户使用已经过期的会话标识符再次访问服务器,即使这个会话标识符的文本文件还没有删除,系统也不应该允许用户使用原来的会话。
· 同时,应该存在一种更新会话文本文件最后改动时间的机制,使得用户在会话过期时限之前返回时会话总是保持最新且合法的状态数据。
四、实现伪会话管理机制
下面所介绍的工程称为PseudoSession,它是伪会话机制一个很简单的实现。考虑到移植性,我们以JavaBean的形式实现它。PseudoSessionBean的完整代码可以从本文后面
下载。
PseudoSessionBean拥有如下域(Field):
public String path;public long timeOut;
path是保存所有会话文本文件的目录。如果Web服务器的数量在一个以上,这个目录必须允许所有服务器访问。然而,为了防止用户直接访问这些文本文件,这个路径应该不允许用户直接访问。解决这个问题的一种方法是使用Web网站根之外的目录。
timeOut是用户的最后一个请求到会话过期作废之间的时间。在PseudoSessionBean的代码清单中,timeOut设置成了以毫秒表示的20分钟,这是一个比较合理的超时时间值。对于任何用户,如果他在这个超时时间之后才继续发出请求,他将得到一个新的会话标识符。
PseudoSessionBean有4个方法:getSessionID,setValue,getValue,deleteAllInvalidSessions。
4.1 getSessionID方法
getSessionID方法的声明如下:
public String getSessionID(HttpServletRequest request)
这个方法应该在每一个JSP页面的开头调用。它完成如下任务:
· 如果用户是第一次访问,则为该用户设定一个新的会话标识符。
· 检查URL所带会话标识符的合法性。如果会话标识符已经过期,则getSessionID方法返回一个新的会话标识符。
下面我们来看看getSessionID方法的工作过程。
String sessionId = request.getParameter("sessionId");
validSessionIdFound是一个标记,用于指示会话标识符是否合法。validSessionIdFound的初始值是false。
boolean validSessionIdFound = false;
long类型的now变量包含请求出现时的服务器时间。该变量用于确定用户会话的合法性。
long now = System.currentTimeMillis();
如果找到了会话标识符,则getSessionID方法检查它的合法性。检查过程如下:
· 一个合法的会话标识符必须有对应的同名文本文件。
· 文件的最后修改时间加上timeO