背景介绍
PHPChina论坛是国内早一批的技术型论坛,在Discuz的基础上开发。Discuz作为国内选用最多的论坛CMS系统,的确在搭建论坛站上有许多优势:功能全、搭建快速、模板丰富。PHPChina在今年3月份改版的时候仍旧是在Discuz的框架中进行二次开发,新增了主页和招聘的模块。但是在开发中就感觉到了,在dz上开发的许多不便捷的地方。Discuz毕竟是一个面向过程的框架,不符合现在面向对象的编程思想。还有就是DZ中开发其他非论坛的业务也是很不爽。所以在二期开发的过程中,PHPChina团队选择了另外的框架-Yii2进行开发。
在新的框架上开发并没有什么难点,两个框架并存,最多做一个会员的打通就可以搞定。
由于PHPChina上的会员已经达到了40W+的量,并且当初开发的招聘模块都是基于DZ会员的系统开发的,所以在Yii上开发我们别无选择,只能将DZ中的会员信息对接过来。所以基本的思路就是做一个单点登录,无论是在Yii中还是DZ中都能做到同步登录、退出。
以下介绍都基于本地环境介绍。
新建应用并配置通信
首先说明一下我们应用的目录结构:在本地的开发环境中有两个基础文件夹,一个为trunk_dz一个为trunk_yii。这两个文件夹对应了两个不同的框架。
然后你需要去discuz的官网上下载一个Ucenter的安装包,链接地址:http://www.comsenz.com/downloads/install/ucenter,下载适合你版本和编码的Ucenter。然后将解压后的advanced文件夹中的uc_client和example下的api、include、config.inc.php这几个文件和文件夹复制到你的新应用的跟目录下,在本例中我应该复制到trunk_yii下。
进入DZ的管理后台,进入Ucenter中心点击左侧的应用管理,点击添加新应用。
选择自定义安装方式,应用类型为DiscuzX,应用名称随意填(如PPCyii),应用的URL:http://localhost/phpchina_pro/trunk_yii,应用IP:127.0.0.1,最后的开启同步登录和接受通知选择是,然后点击提交。提交完成后,在应用管理页面可以看到你刚刚添加的应用,点击该应用。将该应用的通信秘钥复制出来,添加到yii目录下的config.inc.php中的UC_KEY中,并将此文件中的参数配置完整。然后回到你的应用列表中,右侧显示通信成功则表示配置正确。
通信成功后我们已经做好了第一步准备工作。
为你的Yii应用添加参数配置
至此我们还需要面临一个问题,两个框架并存,路由是不通的。从DZ页面进来的用户是不能路由到YII的应用中的。我们解决这个问题的方法就是配置参数,将两个框架互相要用到的URL地址配置成全路径的参数形式,比如DZ要跳转到Yii中的导航页面,需要在DZ后台的导航设置中的URL中填写http://localhost/phpchina_pro/trunk_tii/index.php这样才能实现两个框架不同路由的跳转。
你可以在你的Yii应用中需要跳转到DZ的URL的地方都以配置参数的形式配置URL,比如在Yii的登录链接中你可以配置为http://localhost/phpchina_pro/trunk_dz/member.php?mod=logging&action=login,这样在你的Yii应用中点击登录就会跳转到DZ的登录应用。这样只需要做一个单点登录,将DZ登录的信息同步到Yii中即可。
实现同步登录、退出
本来做同步登录、退出之前的想法是将DZ的会员SESSION信息储存到Redis上,这样只需将php配置中Session的存储方式由文件改成Redis就可以轻松实现。但是仔细研究才发现,DZ里根本没有Session。PlanA计划失败。
然后就想到了用DZ的Ucenter做同步登录。后来发现其实也只能用这种方法,因为同步退出必须依赖Ucenter。
Ucenter同步登录的原理就是DZ解析cookie信息。好在我们的应用都在同一个域名下,cookie是同步的,只需要将cookie解密出来即可获得用户的登录信息。
首先你需要在Yii中引入刚才复制到Yii根目录的config.inc.php和uc_client/client.php文件。
直接上代码了
if(!empty($_COOKIE[$cookie_auth]) )
{
$key = Yii::$app->params['uc_key'];
list($user_psw, $user_uid) = explode("\t", uc_authcode($_COOKIE[$cookie_auth], 'DECODE',$key));
}
上面的$cookie_auth为我配置的cookie参数,其实为DZ cookie中的pre_cookie,你可以打开调试台看到你的cookie参数,前面有一个前缀将你的这个pre_auth换成上面的$cookie_auth即可。
还有一个$key参数。这个参数其实是你在第一步添加新应用的UC_KEY参数,用来解密cookie的。但是坑爹的是一开我怎么解密都不成功。后来在网上查资料和阅读登录加密的源码才发现这是个坑爹的地方。
原来在DZ登录加密的时候使用的不是UC_KEY加密的,而是用一个authkey加密的。加密和解密的参数不一样肯定是解密不出来的啊!所以现在只能去改源码了。找到DZ目录下的source\function\function_core.php文件,搜索authcode函数。这个函数中有一个$key参数,默认为空。现在我让他不为空,随便写点什么,比如‘PHPChina’。然后在上面的代码中将$key赋值为‘PHPChina’。这样在DZ未登录的情况下是没有pre_auth这个cookie的,登录后我们解析这个cookie就可获得登录用户的密码和uid了。然后我有了uid再去数据库里查询用户的信息即可。至此登录就完成了。
下面说一下退出。
退出也要用到UC的函数来处理。
public function actionLogOut(){
$script = uc_user_synlogout($_SESSION['uid']);
echo $script;
$msg_data = msg_data('退出成功',Yii::$app->request->getReferrer());
return $this->render('@common_web/msg',['msg_data'=>$msg_data]);
}
只需要在你的Yii应用退出上路由到这个方法,就会实现同步退出。记得一定要将$script输出,这个变量存储了一段JS代码,是用来消除cookie的。然后做一个提示用户退出成功的提示消息就可以了。
希望这篇文章可以帮到有同样需求的朋友,记得来PHPChina玩!