惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LangChain Blog
V
V2EX
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
WordPress大学
WordPress大学
有赞技术团队
有赞技术团队
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
小众软件
小众软件
Vercel News
Vercel News
博客园 - 司徒正美
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
J
Java Code Geeks
P
Proofpoint News Feed
MongoDB | Blog
MongoDB | Blog
B
Blog
美团技术团队
量子位

博客园 - 朱春雷

漫谈为消费者网购决策服务产品的创新 也谈盛大C2C平台能否撼动淘宝 电子商务新十年:从对互联网的功能应用到精神应用 保障消费者知情权是食品安全管理的重心 电子商务与媒体融合之探析 使用MySQL Migration Toolkit快速将Oracle数据导入MySQL Windows上安装Apache2、PHP5、MySQL5及与Resin配合实现多系统之整合 自觉培养“舆商” 争做成功网商 面对危机与挑战 更需创业之精神 企消互动广告:企业营销策略变革的必由之路 我创业之路的“足迹”连缀——2008年新浪首届“我的创业路”征文 对称与沟通:让电子商务走进消费者心中——电子商务发展趋势探析之四 企消互动广告:网络时代广告活动的创新形式——兼谈杜丽反败为胜对企业的启示 和而不同 沟通致谐 走向融合:电子商务与传统企业的嫁接——电子商务发展趋势探析之三 电子商务下一站:由网络消费媒体导向——电子商务发展趋势探析之二 企业社会责任与消费者话语权 后阿里巴巴时代:从消费资本化理论“望远镜”中探视——电子商务发展趋势探析之一 情感营销的秘诀:这样的服务真能感动消费者
JSP网站与phpwind论坛同步登入的解决思路
朱春雷 · 2010-03-25 · via 博客园 - 朱春雷

 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之中。