琢思磋文轩

学问之道贵能下人求告为善,赡才之径假人所长补已之短

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  93 随笔 :: 0 文章 :: 117 评论 :: 2 引用

公告

 JSP网站与phpwind论坛同步登入的解决思路

 

在上一篇文章中,笔者介绍了在Windows上安装ApachePHPMySQL等软件的过程,以及ApacheResin整合的方法。在这篇文章中,笔者将介绍JSP网站如何与phpwind论坛实现同步登入和同步退出的方案思路。本文以phpwind 7.5 SP3的源码为例,但由于笔者曾在源码中插入过一些测试代码,后虽作了删除,但尚不保证下文中所示代码的行数完全与源码一致,请自行在提示行数所定位的上下几行中查找。

 

一、phpwindCookie是如何产生的

 

phpwind是通过Cookie的方式来判断当前用户是否已经登入,因此要实现JSP网站与phpwind同步登入和同步退出功能的要点,就在于JSP网站的程序能捕获并分析phpwind生成的Cookie,同时JSP网站的程序还应能生成同样的Cookie,以便访问phpwind论坛时可以自动登入。下面来看下phpwind对于登入用户所生成的Cookie的信息:


 

在上图的Cookie信息中,08383_winduser及其所对应的值就是判断phpwind登入与退出状态的依据,对它的分析也是本文的重点所在。

 

先来看下08383_winduser08383是如何生成的。在login.php文件的84行找到:

Cookie("winduser",StrCode($winduid."\t".$windpwd."\t".$safecv),$cktime);

Cookie函数的作用就是向客户端写Cookie,其函数定义在common.php文件的145行:

function Cookie($ck_Var,$ck_Value,$ck_Time='F',$p=true){ }

从中可知第一个参数是Cookie的键名,第二个参数是Cookie的值,这样通过函数调用传递给$ck_Var的值就是winduser,但我们在Cookie信息中看到的却是08383_winduser,那么这08383是从何而来呢?细看下面的代码,我们会发现在173行有这样的语句:

$ck_Var = CookiePre().'_'.$ck_Var;

看来08383必定是由CookiePre函数所产生的,找到189CookiePre函数的定义:

function CookiePre() {

         static $pre = null;

         !isset($pre) && $pre = substr(md5($GLOBALS['db_sitehash']),0,5);

         return $pre;

}

 

这就知道了原来此08383md5($GLOBALS['db_sitehash'])的前5个字符,而$GLOBALS['db_sitehash']pw_config表中的数据db_sitehash所对应的值,这样键名的产生过程就清楚了。下面再来看如何生成键值。

 

从上文中可知键值其实就是StrCode($winduid."\t".$windpwd."\t".$safecv)common.php文件中第241StrCode函数的定义:

function StrCode($string,$action='ENCODE') { }

可以知道第一个参数是被加密或解密的字符串,第二个参数是表示加密(ENCODE)或是解密(DECODE),默认为加密。其代码中$GLOBALS['pwServer']['HTTP_USER_AGENT']表示的是Request请求中的User-Agent头信息,$GLOBALS['db_hash'] pw_config表中的数据db_hash所对应的值。那么传递给StrCode函数的实参$winduid."\t".$windpwd."\t".$safecv又是如何产生的呢?

login.php文件的第6670行分别有如下代码:

$logininfo = checkpass($pwuser, $md5_pwpwd, $safecv, $lgt);

list($winduid, $groupid, $windpwd, $showmsginfo) = $logininfo;

由此可知StrCode函数的实参是由checkpass函数产生的,在checkpass.php文件第49行找到checkpass函数的定义:

function checkpass($username, $password, $safecv, $lgt=0) { }

可以知道第一个参数是用户名,第二个参数是md5加密过的用户密码,第三个参数是经过处理的用户安全问题。其返回值中的第一个值、第三个值分别与StrCode函数实参中的$winduid$windpwd相对应,其中$winduidpw_members表中对应的uid。而$windpwd的产生较为复杂,在第111行可以看到如下代码:

$windpwd = PwdCode($password);

因此可知$windpwd是由PwdCode函数所产生的,在common.php文件的第227行找到PwdCode函数定义:

function PwdCode($pwd) {

return md5($GLOBALS['pwServer']['HTTP_USER_AGENT'].$pwd.$GLOBALS['db_hash']);

}

这样就明白了,$windpwd其实就是Request请求中的User-Agent头信息的字符串、用md5加密过的用户密码、pw_config表中数据db_hash所对应值,三者依次拼接而成的字符串进行一次md5加密之后所产生的字符串,真是够复杂的,看来phpwind为了安全也是煞费苦心啊!

最后StrCode函数实参中就剩下$safecv了,它是由questcode函数产生,在checkpass.php文件的第211行找到questcode函数的定义:

function questcode($question,$customquest,$answer) {

$question = $question=='-1' ? $customquest : $question;

return $question ? substr(md5(md5($question).md5($answer)),8,10) : '';

}

$safecv的产生过程也够复杂的,相信大家通过上面的讲解也能明白这个产生过程了,那么笔者也就不多费口舌,太累人了!

 

二、phpwind是如何从Cookie中获取信息

 

PhpwindCookie中获取用户信息的代码在global.php文件第152行:

list($winduid,$windpwd,$safecv)=explode("\t",addslashes(StrCode(GetCookie('winduser'),'DECODE')));

   

    其重点在于StrCode(GetCookie('winduser'),'DECODE'),作用是将从Cookie中获取的值采用base64方式进行解码。解码之后的字符串用"\t"分割为三段,第一段是uid,第二段是由上文所提到的PwdCode函数生成的字符串,第三段是由上文所提到的questcode函数生成的字段串,分别存入$winduid$windpwd$safecv中。之后就可以通过该uid来获取用户信息,并验证相关的密码与安全问题是否一致了。

 

    三、实现与phpwind论坛同步登入和同步退出的思路

 

要做到同步登入和同步退出,即用户在JSP网站这边登入后访问phpwind时用户已为登入状态,在phpwind登入后访问JSP网站也为登入状态,退出亦然。这样就要求在JSP网站这边用java实现两个功能,一个是从Cookie中读取由phpwind生成的winduser的值并加以解析,另一个是用户登入时采用类似于phpwind的方式生成Cookie,以便phpwind论坛识别用户状态。由于实现的代码较为简单,只要将上文提到的这些函数翻译成java的代码就行了,因此笔者在此主要介绍一下思路和可能遇到的问题。

 

对于从Cookie中读取由phpwind生成的winduser的值并加以解析,笔者是将这部分代码写在一个Filter里。在此Filter中,读取Cookie中的值然后调用StrCode函数进行解码,从而得到uid。之后通过uid查询数据库得到用户对象,验证其密码与安全问题是否正确。如果都正确的话,则将用户对象存入Session中。下次需要用到该用户对象时,直接从Session中获取,而不再通过调用StrCode函数进行解码及查询数据库得到用户对象。

 

这其中要注意解决的问题是,由于采用在Session中传递用户对象,可能会出现phpwind论坛已经退出或改换用户重新登入,但是在另一浏览窗口访问的JSP网站,由于Session中的对象没有失效,继续访问别的页面时还处于原用户登入状态。笔者的解决方法是设置一个静态变量来保存Cookiewinduser的值,一旦发现新值变空或与原保留值不同,则说明在phpwind论坛那边已经退出或以新用户名登入了。

 

    对于JSP网站这边,用户登入时调用StrCode函数来生成类似phpwind方式的Cookie,这样以便phpwind论坛识别用户状态。此外,为了使phpwindJSP网站共用一个Cookie,需要修改phpwind中的config.php文件,将$db_ckdomain设置“.XXX.com”的形式。同步退出的实现较为简单,只要将Cookie中的值置空即可,笔者在此不再赘述。

 

    好了,在本文中笔者主要介绍了phpwindCookie产生方式,以及phpwind是如何从Cookie中获取信息,并简要介绍了与phpwind论坛实现同步登入的思路。在下一篇文章中,笔者将介绍一下如何将Oracle中的数据快速便利的导入到MySQL之中。

posted on 2010-03-25 20:46 朱春雷 阅读(...) 评论(...) 编辑 收藏