有一个php项目,需要和disucz整合,使用同步登录,统一使用dz的用户数据、短信平台等。以前也作过公用dz用户同步登录,简单的require()disucz的incluce/common.inc.php文件到自己的项目,就可以实现用户同步登录。但是这样的话,要实现共享用户数据、短信平台就比较麻烦。
在康盛的网站和论坛翻了一下,发现康盛推出了ucenter这个平台,可以很方便的整合康盛旗下的各个产品及第三方应用。
根据用户说明,先安装uc,再安装dz,然后把uc安装包中的example独立出来架设一个站点。然后根据开发指南,到uc的后台中添加应用,之后应用就可以与dz共享部分数据了。
本来以为会是个很简单的规程,但是实际操作中却出现了两个难题。
一、uc后台添加应用后检查通信情况的时候出现通信失败:
这个经过排查,原来是example中的api/uc.php中要require的mysql类文件失败,
在uc.php的61行附近,有以下代码:
require_once discuz_root.'./include/db_'.$database.'.class.php';
而其中的$database并未定义,导致require失败,解决的办法是在example项目的根目录下的config.inc.php中增加以下代码:
$database = 'mysql';
这样uc后台就会显示通信成功,至此,这个问题解决了。
二、无法同步登录、注销:
由于自己的项目是本地无用户数据的,直接调用uc的用户数据,所以以下的测试都是用ucexampe_1.php。
我遇到的情况是这样的:
在example中登陆,dz显示已登陆;在example中注销,dz同步注销;在dz中登陆,example未登录;在dz中注销,example未注销。
为了这个问题,我在dz的网站上翻了2天,并为找到任何解决的办法,其间还pm过康盛团队的人,但是并为收到任何回复。
今天下午,在dz的论坛看到一篇文章,其中有一个连接,是分析uc通信过程的,
http://hi.baidu.com/winterfog/bl ... 80709d0b7b8208.html看了这个文章后,根据文章中提到的一点,逐步debug。
1、在example的api/uc.php的 $action = $get['action']下增加以下一行代码:
- echo "<pre>";var_dump($get);echo "</pre>";die("<hr>api\uc.php");
复制代码然后在dz中尝试登陆,获得dz中访问example的连接,检查输出内容,发现输出内容完全正常。
接下来继续看uc.php的代码,发现了多处读取数据库的代码,由于自己的项目在用户这一块无须读取数据库,所以暂时将uc.php中同步登录的读取数据库的部分注释掉。
根据uc.php的流程,检查synlogin函数,在这里出现了一些让人摸不早头脑的代码
- require_once $this->appdir.'./forumdata/cache/cache_settings.php';
复制代码$this->appdir的值为example应用的物理路径,而此路径下并无forumdata目录,也就没有cache_settings.php这个问题了。不过,这个文件应该是dz目录下对应的文件。
好吧,你要require,那我就去copy过来给你。后来发现,这是多此一举,这个文件根本就不需要。
继续往下面检查,发现了很多看起来是discuz里面的变量和代码。终于看到重点了。原始代码如下:
- require $this->dbconfig;
- require_once $this->appdir.'./include/db_'.$database.'.class.php';
- require_once $this->appdir.'./forumdata/cache/cache_settings.php';
- $db = new dbstuff;
- $this->db->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect, true, $dbcharset ? $dbcharset : $charset);
- unset($dbhost, $dbuser, $dbpw, $dbname, $pconnect);
- $cookietime = 2592000;
- $discuz_auth_key =
- md5($_dcache['settings']['authkey'].$_server['http_user_agent']);
- header('p3p: cp="cura adma deva psao psdo our bus uni pur int dem sta pre com nav otc noi dsp cor"');
- $uid = intval($uid);
- $query = $this->db->query("select username, uid,password, secques from ".$this->tablepre."members where uid='$uid'");
- if($member = $this->db->fetch_array($query)) {
- _setcookie('sid', '', -86400 * 365);
- _setcookie('cookietime', $cookietime, 31536000);
- _setcookie('auth',
- _authcode("$member[password]\t$member[secques]\t$member[uid]", 'encode', $discuz_auth_key), $cookietime);
- } else {
- _setcookie('cookietime', $cookietime, 31536000);
- _setcookie('loginuser', $username, $cookietime);
- _setcookie('activationauth', _authcode($username, 'encode', $discuz_auth_key), $cookietime);
- }
复制代码这里的代码实现以下的功能:
连接数据库->设置cookie的过期时间->生成authcode函数所需要的auth_key->检索数据库,获得当前用户的用户名、密码、id,然后设置cookie。
之前提到过,我这个应用暂时不需要读取数据库,所以把数据库相关的代码都注释掉。只剩下以下的代码:
- $cookietime = 2592000;
- $discuz_auth_key =
- md5($_dcache['settings']['authkey'].$_server['http_user_agent']);
- header('p3p: cp="cura adma deva psao psdo our bus uni pur int dem sta pre com nav otc noi dsp cor"');
- $uid = intval($uid);
- _setcookie('cookietime', $cookietime, 31536000);
- _setcookie('loginuser', $username, $cookietime);
- _setcookie('activationauth', _authcode($username, 'encode', $discuz_auth_key), $cookietime);
复制代码至此已经找到问题的根本了:
1、authcode所使用的auth_key本应用本身的设定不一样。应用本身设定为123456(这个在config.inc.php中设定,也就是uc_key),而上面的代码是用$discuz_auth_key,直接将$discuz_auth_key更改为uc_key
2、authcode加密的内容有问题,ucexample_1.php判断是否同步登录使用以下的代码
- if(!empty($_cookie['example_auth'])) {
- list($example_uid, $example_username) = explode("\t",
- uc_authcode($_cookie['example_auth'], 'decode'));
- var_dump(explode("\t", uc_authcode($_cookie['example_auth'], 'decode',
- uc_key)));
- } else {
- $example_uid = $example_username = '';
- }
复制代码通过解密cookie,获得$example_uid和$example_username两个变量名,而uc.php中进行加密的只有$username一个,将之修改为$uid."\t".$username
到此,已经解决了本地应用无用户数据库的同步登录问题。
接下来说一些感想:
1、作为康盛的关键产品ucenter,在
www.discuz.net上的ucenter开发版面人气并不旺,而且管理团队和开发团队最近也很少关注关注该版面,用户提出的问题也很少得到解决的。
2、官方的开发指南错漏百出,最低级的错误是未定义$database这个非常重要的变量。
3、作为一个和dz相对独立的产品,其中的例程所使用的代码很多是照搬dz的,如果正常工作那倒没问题,但是却无法正常工作,连authcode这样关键函数所使用的auth_key居然也弄错,希望官方能仔细检查。