商会资讯

 找回密码
 立即注册

QQ登录

只需一步,快速开始

用新浪微博连接

一步搞定

搜索
热搜: 活动 交友 discuz

关于康盛UCenter整合应用的一些经验,关于同步登录的

已有 2153 次阅读2009-9-28 13:39

有一个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']下增加以下一行代码:
  1.     echo "<pre>";var_dump($get);echo "</pre>";die("<hr>api\uc.php");
复制代码
然后在dz中尝试登陆,获得dz中访问example的连接,检查输出内容,发现输出内容完全正常。

    接下来继续看uc.php的代码,发现了多处读取数据库的代码,由于自己的项目在用户这一块无须读取数据库,所以暂时将uc.php中同步登录的读取数据库的部分注释掉。

    根据uc.php的流程,检查synlogin函数,在这里出现了一些让人摸不早头脑的代码
  1.     require_once $this->appdir.'./forumdata/cache/cache_settings.php';
复制代码
$this->appdir的值为example应用的物理路径,而此路径下并无forumdata目录,也就没有cache_settings.php这个问题了。不过,这个文件应该是dz目录下对应的文件。
    好吧,你要require,那我就去copy过来给你。后来发现,这是多此一举,这个文件根本就不需要。

    继续往下面检查,发现了很多看起来是discuz里面的变量和代码。终于看到重点了。原始代码如下:
  1.         require $this->dbconfig;
  2.         require_once $this->appdir.'./include/db_'.$database.'.class.php';
  3.         require_once $this->appdir.'./forumdata/cache/cache_settings.php';

  4.         $db = new dbstuff;
  5.         $this->db->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect, true, $dbcharset ? $dbcharset : $charset);
  6.         unset($dbhost, $dbuser, $dbpw, $dbname, $pconnect);
  7.         $cookietime = 2592000;
  8.         $discuz_auth_key =
  9. md5($_dcache['settings']['authkey'].$_server['http_user_agent']);
  10.         header('p3p: cp="cura adma deva psao psdo our bus uni pur int dem sta pre com nav otc noi dsp cor"');
  11.         $uid = intval($uid);
  12.         $query = $this->db->query("select username, uid,password, secques from ".$this->tablepre."members where uid='$uid'");
  13.         if($member = $this->db->fetch_array($query)) {
  14.             _setcookie('sid', '', -86400 * 365);
  15.             _setcookie('cookietime', $cookietime, 31536000);
  16.             _setcookie('auth',
  17. _authcode("$member[password]\t$member[secques]\t$member[uid]", 'encode', $discuz_auth_key), $cookietime);
  18.         } else {
  19.             _setcookie('cookietime', $cookietime, 31536000);
  20.             _setcookie('loginuser', $username, $cookietime);
  21.             _setcookie('activationauth', _authcode($username, 'encode', $discuz_auth_key), $cookietime);
  22.         }
复制代码
这里的代码实现以下的功能:

    连接数据库->设置cookie的过期时间->生成authcode函数所需要的auth_key->检索数据库,获得当前用户的用户名、密码、id,然后设置cookie。

    之前提到过,我这个应用暂时不需要读取数据库,所以把数据库相关的代码都注释掉。只剩下以下的代码:
  1.        $cookietime = 2592000;
  2.        $discuz_auth_key =
  3. md5($_dcache['settings']['authkey'].$_server['http_user_agent']);
  4.         header('p3p: cp="cura adma deva psao psdo our bus uni pur int dem sta pre com nav otc noi dsp cor"');
  5.         $uid = intval($uid);
  6.             _setcookie('cookietime', $cookietime, 31536000);
  7.             _setcookie('loginuser', $username, $cookietime);
  8.             _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判断是否同步登录使用以下的代码
  1. if(!empty($_cookie['example_auth'])) {
  2.     list($example_uid, $example_username) = explode("\t",
  3. uc_authcode($_cookie['example_auth'], 'decode'));
  4.     var_dump(explode("\t", uc_authcode($_cookie['example_auth'], 'decode',
  5. uc_key)));
  6. } else {
  7.     $example_uid = $example_username = '';
  8. }
复制代码
通过解密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居然也弄错,希望官方能仔细检查。
收藏 分享邀请 转发到微博 举报

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 立即注册

回顶部