JForum源代码研究—Cookie,Session

 

先熟悉一下javax.servlet.http.Cookie和javax.servlet.http.HttpSession。

 

JForum系统有一项功能是:实时显示在线的注册会员数、匿名访客数。

 

登录本机的JForum,并选择“自动登录”后,可以看到如下的Cookie信息:

JForum源代码研究—Cookie,Session

 

SystemGlobals.properties中关于Cookie的配置如下:

cookie.name.data = jforumUserId
cookie.name.user = jforumUserInfo
cookie.name.autologin = jforumAutoLogin
cookie.name.userHash = jforumUserHash

 

在Eclipse中,使用“文件搜索”搜索“COOKIE_NAME_USER”,只有一条记录。可见,在2.1.8版本中根本没有用到jforumUserInfo。

 

jforumUserId的值为jforum_users表中user_id列的值,匿名用户的user_id为1。登录时如果选择了“自动登录”,则jforumAutoLogin的值为1,jforumUserHash的值为一个散列值,否则,客户端不会有jforumAutoLogin和jforumUserHash。

 

jforumUserHash的生成规则如下(即systemHash):

// Generate the user-specific hash
String systemHash = MD5.crypt(SystemGlobals.getValue(ConfigKeys.USER_HASH_SEQUENCE) + user.getId());
String userHash = MD5.crypt(System.currentTimeMillis() + systemHash);
					
// Persist the user hash
UserDAO dao = DataAccessDriver.getInstance().newUserDAO();
dao.saveUserAuthHash(user.getId(), userHash);
					
systemHash = MD5.crypt(userHash);

  其中,SystemGlobals.getValue()是读取配置值,默认值为:

user.hash.sequence = 04904SDFfhfh449911-**%$nvMDFHDhskda6546546as4df4ads6f54ads654

在正式环境下使用JForum时,应该修改该值。

 

net.jforum.entities.UserSession用于抽象用户会话信息。很奇怪它的构造函数:

	public UserSession() {}

	public UserSession(UserSession us)
	{
		if (us.getStartTime() != null) {
			this.startTime = new Date(us.getStartTime().getTime());
		}

		if (us.getLastVisit() != null) {
			this.lastVisit = new Date(us.getLastVisit().getTime());
		}
		
		this.sessionTime = us.getSessionTime();
		this.userId = us.getUserId();
		this.sessionId = us.getSessionId();
		this.username = us.getUsername();
		this.autoLogin = us.getAutoLogin();
		this.lang = us.getLang();
		this.privateMessages = us.getPrivateMessages();
		this.imageCaptcha = us.imageCaptcha;
		this.ip = us.getIp();
	}

  用一个UserSession对象来构造另一个UserSession对象?第6、10行,为什么不直接this.startTime = us.getStartTime();而多此一举呢?我觉得这样做的目的是想实现“clone”效果,利用一个UserSession对象,克隆另一个UserSession对象。

 

 

关于net.jforum.SessionFacade类

从类名中Facade单词中可以看出,作者想让SessionFacade担任UserSession的门面,即门面模式。门面模式是对象的结构模式。外部与一个子系统的通信必须通过一个统一的门面对象进行,这就是门面模式。[1]     在门面模式中,通常只需要一个门面类,并且此门面类只有一个实例,换言之它是一个单例类。[2]    具体到JForum而言,“子系统”包括:UserSession类、CacheEngine实现类以及和Session DAO方法相关的类。SessionFacade类中除了setCacheEngine()方法外,都是静态方法,也算是单例类了。这些和教科书中所说的还是比较一致的。

 

门面不是不能越过的。JForum中也有一小部分代码直接使用的UserSession us = new UserSession(); us.方法调用,即越过了SessionFacade门面。

 

让我们再读一下《Java与模式》第32章 门面(Facade)模式和《设计模式》第4.5节 FACADE(外观)——对象结构模式吧。

 

 

 

[1] 引自《Java与模式》P561

[2] 引自《Java与模式》P563