忘记密码?

一键登录

草根吧源码论坛

项目整合Discuz UCenter,整合Discuz UCenter

查看: 107|回复: 0

项目整合Discuz UCenter,整合Discuz UCenter

[复制链接]

56

主题

113

热度

69

贡献

步入草根

Rank: 1

发表于 2016-9-7 14:45:08 | 显示全部楼层 |阅读模式 | 百度  360  谷歌 
分享到:

市场就是力量,discuz是国内人气最高,使用最广泛的论坛系统,发展到今天它已经整合了论坛、门户、博客、CMS等版块,内容丰富,深受用户的喜爱,一直以来很多用户用它来整合自己的应用。由于discuz版块众多,系统相对封装,源代码缺少注释,api资料不够丰富,官方对discuz用户的咨询也并非卖力,而网上资料不是版本陈旧就是鱼龙混杂。对于想整合discuz论坛的朋友存在一定的难度。因此,如果你想美好整合discuz的话,不妨耐心看完以下提示。

一、准备工作

1、uc api说明书,通读全文。参考http://faq.comsenz.com/library/UCenter/introduction/introduction_list.htm(官方),了解同步登陆机制

2、uc 后台添加应用说明。参考http://faq.comsenz.com/viewnews-506(官方) http://wenku.baidu.com/view/3790fdd7195f312b3169a588.html(草根)

3、uc client客户端必要代码,这里下载

4、如果是x3后面的版本,请先更改bug,参见http://www.discuz.net/thread-3505581-1-1.html

解决方案如下:
\source\class\discuz的discuz_application.php 查找


<?php
  1. private function _xss_check() {
  2.                 static $check = array('"', '>', '<', '\'', '(', ')', 'CONTENT-TRANSFER-ENCODING');
  3.                         
  4.                 if(isset($_GET['formhash']) && $_GET['formhash'] !== formhash()) {
  5.                         system_error('request_tainting');
  6.                 }

  7.                 if($_SERVER['REQUEST_METHOD'] == 'GET' ) {
  8.                         $temp = $_SERVER['REQUEST_URI'];
  9.                 } elseif(empty ($_GET['formhash'])) {
  10.                         $temp = $_SERVER['REQUEST_URI'].file_get_contents('php://input');
  11.                 } else {
  12.                         $temp = '';
  13.                 }

  14.                 if(!empty($temp)) {
  15.                         $temp = strtoupper(urldecode(urldecode($temp)));
  16.                         foreach ($check as $str) {
  17.                                 if(strpos($temp, $str) !== false) {
  18.                                         system_error('request_tainting');
  19.                                 }
  20.                         }
  21.                 }

  22.                 return true;

  23.         }
复制代码
二、示例
我们学习一门技术时,看看它的技术说明就足够了,但discuz远非如此。discuz不是zend frame、dedecms、ci这些白开水的东西,没有一点钻研精神和爱折腾的气质是无法理解它深奥的内涵,更不用说驾驭它。要达到成功,我们需要有详尽的说明文字,另外还需要配备必要的图片,虽然有了这些你也未必能够成功。
先看一下我的项目结构
草根吧 项目整合Discuz UCenter,整合Discuz UCenter 项目,dedecms,frame,说明书,discuz 精品教程 201507566623161
tanahk 是真正的项目地址,x3.2是我的discuz论坛,打开它
草根吧 项目整合Discuz UCenter,整合Discuz UCenter 项目,dedecms,frame,说明书,discuz 精品教程 201507573036330
可以看到这个discuz x3.2已经整合了Ucenter,其中uc_server是uc服务器,uc_client是客户端,uc_client这个文件夹在discuz x、discuz home、discuz xspace等产品中都是已经捆绑好的。需要记住的一点,在整个共用站点系统中,我们只需要一个uc_client,因为uc_server只会在它定义的uc_client路径中寻找data文件中的apps数组。
因此在多站点同步登陆登出的关键文件只有两个,一个是config.ini.php,另一个是uc.php。前者告诉uc_server我们这个应用的配置,后者供uc_server调用。
把examples/api/uc.php文件复制到我们的tanahk/api/uc.php,examples/config.inc.php和examples/include也添加进来。目录结构变为
草根吧 项目整合Discuz UCenter,整合Discuz UCenter 项目,dedecms,frame,说明书,discuz 精品教程 211558103858274
code文件夹我用来查看一些源码。
好了,现在可以在UCenter后台添加我们的项目应用了。uc的后台一般为http://www.xxx.com/x3.2/uc_server/admin.php
草根吧 项目整合Discuz UCenter,整合Discuz UCenter 项目,dedecms,frame,说明书,discuz 精品教程 201508001464329
选择“应用管理”--“添加新应用”
参考上面准备工作中2。
应用类型:其它
应用名称:Tanahk,这里只能填写英文
通信密钥:随意一串不多于64位的字母数字。
应用的物理路径:可以为空,只要应用主url填写正确
应用接口文件名称:保留,uc.php,不用填api/uc.php
是否开启同步登陆:是,这是关键,以后多个项目共用一个uc就行了,不用自己新建一套用户系统。
提交
提交后一般是通信错误的。
我们先修改tanahk/api/config.inc.php 。这里的数据非常重要,如果安装了discuz x或其它discuz产品,最好对照discuz root/config下面的配置文件修改。
  1. <?php

  2. define('UC_CONNECT', null);                // 连接 UCenter 的方式: mysql/NULL, 默认为空时为 fscoketopen()
  3.                             // mysql 是直接连接的数据库, 经实践,还是填写null好。mysql有时无法执行

  4. //数据库相关 (mysql 连接时, 并且没有设置 UC_DBLINK 时, 需要配置以下变量)
  5. define('UC_DBHOST', 'localhost');            // UCenter 数据库主机
  6. define('UC_DBUSER', 'root');                // UCenter 数据库用户名
  7. define('UC_DBPW', '111111');                    // UCenter 数据库密码
  8. define('UC_DBNAME', 'ultrax');                // UCenter 数据库名称
  9. define('UC_DBCHARSET', 'utf8');                // UCenter 数据库字符集
  10. define('UC_DBTABLEPRE', '`ultrax`.pre_ucenter_');            // UCenter 数据库表前缀
  11. define('UC_DBCONNECT', 0);                    // 是否持久化链接

  12. //通信相关
  13. define('UC_KEY', '…');                // 与 UCenter 的通信密钥, 要与注册应用时填写的保持一致
  14. define('UC_API', 'http://www.xxx.com/x3.2/uc_server');    // UCenter 的 URL 地址, 在调用头像时依赖此常量
  15. define('UC_CHARSET', 'utf-8');                // UCenter 的字符集
  16. define('UC_IP', '');                    // UCenter 的 IP, 当 UC_CONNECT 为非 mysql 方式时, 并且当前应用服务器解析域名有问题时, 请设置此值
  17. define('UC_APPID', 2);                    // 当前应用的 ID

  18. define('UC_PPP', 20);

  19. //ucexample_2.php 用到的应用程序数据库连接参数
  20. $dbhost = 'localhost';            // 数据库服务器
  21. $dbuser = 'root';            // 数据库用户名
  22. $dbpw = '111111';                // 数据库密码
  23. $dbname = 'ultrax';            // 数据库名
  24. $pconnect = 0;                // 数据库持久连接 0=关闭, 1=打开
  25. $tablepre = '`ultrax`.pre_ucenter_';           // 表名前缀, 同一数据库安装多个论坛请修改此处
  26. $dbcharset = 'utf8';        // MySQL 字符集, 可选 'gbk', 'big5', 'utf8', 'latin1', 留空为按照论坛字符集设定

  27. //同步登录 Cookie 设置
  28. $cookiepre = 'jt_';           // cookie 前缀
  29. $cookiedomain = '';         // cookie 作用域
  30. $cookiepath = '/';        // cookie 作用路径
复制代码
认真对照,特别是UC_KEY与UC_APPID,id一般为2以后的数字,查看uc后台,1被discuz x霸占了。 上面的配置不能遗漏。 UC_DBHOST,如果填写mysql,最好带port,可以包括端口号,例如 “hostname:port”,或者到本地套接字的路径,例如对于 localhost 的 “:/path/to/socket”。UC_PPP:默认值为 20,与 UCenter 日志显示的条数和通知管理显示的条数有关系。
在上述配置最后加上一句 :
  1. $cookiename = 'tanahk';        // 用户自定义的cookie名
复制代码
它用来贮存用户登陆成功后的cookie值。
我们现在需要花大力气修改uc.php。首先是修改开头的常量定义
  1. error_reporting(0);

  2. define('IN_DISCUZ', TRUE);

  3. define('UC_CLIENT_VERSION', '1.5.0');    //note UCenter 版本标识
  4. define('UC_CLIENT_RELEASE', '20081031');

  5. define('API_DELETEUSER', 1);            //note 用户删除 API 接口开关
  6. define('API_RENAMEUSER', 1);            //note 用户改名 API 接口开关
  7. define('API_GETTAG', 1);                //note 获取标签 API 接口开关
  8. define('API_SYNLOGIN', 1);                //note 同步登录 API 接口开关
  9. define('API_SYNLOGOUT', 1);                //note 同步登出 API 接口开关
  10. define('API_UPDATEPW', 1);                //note 更改用户密码 开关
  11. define('API_UPDATEBADWORDS', 1);        //note 更新关键字列表 开关
  12. define('API_UPDATEHOSTS', 1);            //note 更新域名解析缓存 开关
  13. define('API_UPDATEAPPS', 1);            //note 更新应用列表 开关
  14. define('API_UPDATECLIENT', 1);            //note 更新客户端缓存 开关
  15. define('API_UPDATECREDIT', 1);            //note 更新用户积分 开关
  16. define('API_GETCREDITSETTINGS', 1);        //note 向 UCenter 提供积分设置 开关
  17. define('API_GETCREDIT', 1);                //note 获取用户的某项积分 开关
  18. define('API_UPDATECREDITSETTINGS', 1);    //note 更新应用积分设置 开关

  19. define('API_RETURN_SUCCEED', '1');
  20. define('API_RETURN_FAILED', '-1');
  21. define('API_RETURN_FORBIDDEN', '-2');

  22. // 改你真实的discuz地址
  23. define('DISCUZ_ROOT', realpath(dirname(__FILE__) . '/../../x3.2/'));
  24. // 本应用配置路径
  25. define('DISCUZ_UC_CONFIG', realpath(dirname(__FILE__)));
复制代码
然后是修改下面的note通知方式
  1. //note 普通的 http 通知方式
  2. if(!defined('IN_UC')) {
  3.    
  4.     if (!defined('PHP_VERSION_ID'))
  5.     {
  6.         $version = explode('.', PHP_VERSION);
  7.         define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
  8.     }
  9.    
  10.     // set_magic_quotes_runtime 5.3.0版本不赞成使用,5.4.0废弃
  11.     if (PHP_VERSION_ID < 530)
  12.         set_magic_quotes_runtime(0);
  13.    
  14.     // 修改常量MAGIC_QUOTES_GPC,与php5.4接地气,让它一直为false
  15.     define('MAGIC_QUOTES_GPC', false);
  16.     require_once DISCUZ_UC_CONFIG . '/config.inc.php';
  17.    
  18.     $GLOBALS['cookiename'] = $cookiename;
  19.     $_DCACHE = $get = $post = array();

  20.     $code = isset($_GET['code']) ? $_GET['code'] : '';
  21.     parse_str(_authcode($code, 'DECODE', UC_KEY), $get);
  22.    
  23.     $timestamp = time();
  24.     if($timestamp - $get['time'] > 3600)
  25.         exit('Authracation has expiried');
  26.         
  27.     if(empty($get))
  28.         exit('Invalid Request');
  29.         
  30.     $action = $get['action'];

  31.     require_once  DISCUZ_ROOT . '/uc_client/lib/xml.class.php';
  32.     $post = xml_unserialize(file_get_contents('php://input'));
  33.    
  34.     if(in_array($get['action'], array('test', 'deleteuser', 'renameuser', 'gettag', 'synlogin', 'synlogout', 'updatepw', 'updatebadwords', 'updatehosts', 'updateapps', 'updateclient', 'updatecredit', 'getcreditsettings', 'updatecreditsettings'))) {
  35.         require_once DISCUZ_UC_CONFIG . '/include/db_mysql.class.php';
  36.         $GLOBALS['db'] = new dbstuff;
  37.         $GLOBALS['db']->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect, true, $dbcharset);
  38.         $GLOBALS['tablepre'] = $tablepre;
  39.         unset($dbhost, $dbuser, $dbpw, $dbname, $pconnect);
  40.         $uc_note = new uc_note();
  41.         exit($uc_note->$get['action']($get, $post));
  42.     } else {
  43.         exit(API_RETURN_FAILED);
  44.     }

  45. //note include 通知方式
  46. } else {
  47.    
  48.     require_once DISCUZ_UC_CONFIG . '/config.inc.php';
  49.     require_once DISCUZ_UC_CONFIG . '/include/db_mysql.class.php';
  50.     $GLOBALS['cookiename'] = $cookiename;
  51.     $GLOBALS['db'] = new dbstuff;   
  52.     $GLOBALS['db']->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect, true, $dbcharset);
  53.     $GLOBALS['tablepre'] = $tablepre;
  54.     unset($dbhost, $dbuser, $dbpw, $dbname, $pconnect);
  55. }
复制代码
上面把我们的$cookiename参数引进来,留给同步登陆函数使用。
  1. $GLOBALS['cookiename'] = $cookiename;
复制代码
修改function uc_note,它其实就是uc_note类的的构造函数。当ucenter有相关举动时通知我们的应用。
  1. function uc_note() {
  2.         $this->appdir = DISCUZ_ROOT;        
  3.         $this->dbconfig = DISCUZ_UC_CONFIG.'/config.inc.php';
  4.         $this->db = $GLOBALS['db'];
  5.         $this->tablepre = $GLOBALS['tablepre'];
  6.     }
复制代码

把uc_client客户端指向discuz X3.2的路径,而配置文件指向我们api/目录。
然后修改synlogin/synlogout同步论坛的登入登出函数,把我们的$cookiename引进来
  1. function synlogin($get, $post) {
  2.         $uid = $get['uid'];
  3.         $username = $get['username'];
  4.         if(!API_SYNLOGIN) {
  5.             return API_RETURN_FORBIDDEN;
  6.         }

  7.         header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
  8.         _setcookie($GLOBALS['cookiename'], _authcode($uid."\t".$username, 'ENCODE'));
  9.     }

  10.     function synlogout($get, $post) {
  11.         if(!API_SYNLOGOUT) {
  12.             return API_RETURN_FORBIDDEN;
  13.         }

  14.         //note 同步登出 API 接口
  15.         header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
  16.         _setcookie($GLOBALS['cookiename'], '', -86400 * 365);
  17.     }
复制代码
如上。当用户在论坛中登陆时,它会通知更新我们设定的名为$cookiename的cookie值,而当用户在其它地方退出时,会清除我们的cookie。
因为_setcookie函数要引用全局变量,discuz在uc.php默认把它屏蔽了,因此我们要加进来。
  1. //note 使用该函数前需要 require_once $this->appdir.'/config.inc.php';
  2. function _setcookie($var, $value, $life = 0, $prefix = 1) {
  3.     require_once DISCUZ_UC_CONFIG . '/config.inc.php';
  4.     global $cookiepre, $cookiedomain, $cookiepath, $timestamp, $_SERVER;
  5.     setcookie(($prefix ? $cookiepre : '').$var, $value,
  6.         $life ? $timestamp + $life : 0, $cookiepath,
  7.         $cookiedomain, $_SERVER['SERVER_PORT'] == 443 ? 1 : 0);
  8. }
复制代码
discuz在uc.php后面定义了三个函数,一个_setcookie,它贮存cookie,_authcode加密解密用户cookie或其它文本值,_stripslashes转义字符串。
_authcode是一个使用频率很高,用途广泛的明文加解密函数,在discuz产品或其它php产品中非常常见,我们有必要了解一下。下面是以其原版authcode为例
  1. <?php
  2. // 参数解释
  3. // $string: 明文 或 密文
  4. // $operation:DECODE表示解密,其它表示加密
  5. // $key: 密匙
  6. // $expiry:密文有效期
  7. function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
  8.     // 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙
  9.     // 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
  10.     // 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方
  11.     // 当此值为 0 时,则不产生随机密钥
  12.     $ckey_length = 4;

  13.     // 密匙
  14.     $key = md5($key ? $key : $GLOBALS['discuz_auth_key']);

  15.     // 密匙a会参与加解密
  16.     $keya = md5(substr($key, 0, 16));
  17.     // 密匙b会用来做数据完整性验证
  18.     $keyb = md5(substr($key, 16, 16));
  19.     // 密匙c用于变化生成的密文
  20.     $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
  21.     // 参与运算的密匙
  22.     $cryptkey = $keya.md5($keya.$keyc);
  23.     $key_length = strlen($cryptkey);
  24.     // 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b),解密时会通过这个密匙验证数据完整性
  25.     // 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确
  26.     $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('0d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
  27.     $string_length = strlen($string);
  28.     $result = '';
  29.     $box = range(0, 255);
  30.     $rndkey = array();
  31.     // 产生密匙簿
  32.     for($i = 0; $i <= 255; $i++) {
  33.         $rndkey[$i] = ord($cryptkey[$i % $key_length]);
  34.     }
  35.     // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上并不会增加密文的强度
  36.     for($j = $i = 0; $i < 256; $i++) {
  37.         $j = ($j + $box[$i] + $rndkey[$i]) % 256;
  38.         $tmp = $box[$i];
  39.         $box[$i] = $box[$j];
  40.         $box[$j] = $tmp;
  41.     }
  42.     // 核心加解密部分
  43.     for($a = $j = $i = 0; $i < $string_length; $i++) {
  44.         $a = ($a + 1) % 256;
  45.         $j = ($j + $box[$a]) % 256;
  46.         $tmp = $box[$a];
  47.         $box[$a] = $box[$j];
  48.         $box[$j] = $tmp;
  49.         // 从密匙簿得出密匙进行异或,再转成字符
  50.         $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
  51.     }
  52.     if($operation == 'DECODE') {
  53.         // substr($result, 0, 10) == 0 验证数据有效性
  54.         // substr($result, 0, 10) - time() > 0 验证数据有效性
  55.         // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性
  56.         // 验证数据有效性,请看未加密明文的格式
  57.         if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
  58.             return substr($result, 26);
  59.         } else {
  60.             return '';
  61.         }
  62.     } else {
  63.         // 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因
  64.         // 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码
  65.         return $keyc.str_replace('=', '', base64_encode($result));
  66.     }
  67. }

  68. // 加密
  69. echo authcode("www.nowamagic.net", 'ENCODE');
  70. // 解密
  71. echo authcode(authcode("www.nowamagic.net", 'ENCODE'));
  72. //echo authcode("55e5OxJ5zjgFuqTjFRPdt9ag+fC+GKP9Efq6yWeAAvdQFq+D");
  73. ?>
复制代码
如果配置全部正确,再回到uc后台,点击“应用管理”,应该能显示通信成功了。
草根吧 项目整合Discuz UCenter,整合Discuz UCenter 项目,dedecms,frame,说明书,discuz 精品教程 211558127135831
到这步预防万一,我们再次点击应用2的编辑,进入,复制最下面的“应用的 UCenter 配置信息”,再次对照config.ini.php。这样写法更规范。
草根吧 项目整合Discuz UCenter,整合Discuz UCenter 项目,dedecms,frame,说明书,discuz 精品教程 211626278224499
至此,所有配置都结束。
现在再来分析一下。discuz root/uc_client/client.php是我们第三方网站操纵discuz ucenter的入口,里面定义了很多全局api函数,通过这些函数我们可以实现用户的登陆、退出、获取用户信息等等功能。具体查看官方接口函数这一章节。而tanahk/api/uc.php文件则相反,它是ucenter与我们的网站交互的接口,ucenter的相关动作可以通知到我们的应用。比如用户在论坛的登陆、退出、修改用户密码、修改昵称等。那么它是怎样通知uc.php呢,打开discuz root/uc_server/control/user.php,查看30-52行。
  1. // -1 未开启
  2.     function onsynlogin() {
  3.         $this->init_input();
  4.         $uid = $this->input('uid');

  5.         if($this->app['synlogin']) {
  6.             if($this->user = $_ENV['user']->get_user_by_uid($uid)) {
  7.                 $synstr = '';
  8.                 foreach($this->cache['apps'] as $appid => $app) {
  9.                     if($app['synlogin']) {
  10.                         $synstr .= '<script type="text/javascript" src="'.$app['url'].'/api/'.$app['apifilename'].'?time='.$this->time.'&code='.urlencode($this->authcode('action=synlogin&username='.$this->user['username'].'&uid='.$this->user['uid'].'&password='.$this->user['password']."&time=".$this->time, 'ENCODE', $app['authkey'])).'" reload="1"></script>';
  11.                         if(is_array($app['extra']['extraurl'])) foreach($app['extra']['extraurl'] as $extraurl) {
  12.                             $synstr .= '<script type="text/javascript" src="'.$extraurl.'/api/'.$app['apifilename'].'?time='.$this->time.'&code='.urlencode($this->authcode('action=synlogin&username='.$this->user['username'].'&uid='.$this->user['uid'].'&password='.$this->user['password']."&time=".$this->time, 'ENCODE', $app['authkey'])).'" reload="1"></script>';
  13.                         }
  14.                     }
  15.                 }
  16.                 return $synstr;
  17.             }
  18.         }
  19.         return '';
  20.     }
复制代码
这个是同步登陆函数,注意
  1. if($this->app['synlogin'])
复制代码
是判断我们后台添加的discuz x、discuz home....甚至是我们的第三方应用是否开启了同步登陆。如果在uc后台编辑了“是”那么会在discuz root/uc_server/data/cache/apps.php,及在discuz root/uc_client/data/cache/apps.php下面分别贮存数据。
  1. <?php
  2. $_CACHE['apps'] = array (
  3. =>
  4.   array (
  5.     'appid' => '1',
  6.     'type' => 'DISCUZX',
  7.     'name' => 'Discuz! Board',
  8.     'url' => 'http://www.xxx.com/x3.2',
  9.     'ip' => '',
  10.     'viewprourl' => '',
  11.     'apifilename' => 'uc.php',
  12.     'charset' => '',
  13.     'dbcharset' => '',
  14.     'synlogin' => '1',
  15.     'recvnote' => '1',
  16.     'extra' => false,
  17.     'tagtemplates' => '',
  18.     'allowips' => ''
  19.   ),
  20. =>
  21.   array (
  22.     'appid' => '2',
  23.     'type' => 'OTHER',
  24.     'name' => 'TANAHK',
  25.     'url' => 'http://www.xxx.com/tanahk',
  26.     'ip' => '',
  27.     'viewprourl' => '/space.php?uid=%s',
  28.     'apifilename' => 'uc.php',
  29.     'charset' => '',
  30.     'synlogin' => '1',
  31.     'extra' =>
  32.         array (
  33.           'apppath' => '/…/tanahk/',
  34.           'extraurl' => ''
  35.         ),
  36.     'recvnote' => '1'
  37.   ),
  38.   'UC_API' => 'http://www.xxx.com/x3.2/uc_server'
  39. );

  40. ?>
复制代码
如果在对应数组设置了’synlogin’=>1,那么它就是同步,它是在后台点击“应用管理”的时候自动添加进来的。但如果我们前面的设置有错,没有看到上面的$_CACHE['apps'][2],那么,我们只能照上面的1,复制一份下来。不然在onsynlogin() 函数
  1. foreach($this->cache['apps'] as $appid => $app) {
  2.     ...
  3. }
复制代码
循环时没有找到我们的应用,它就不会发送js通知。
对于使用mvc的应用来说,我们可能还需要把client.php的功能集成到我们的model层,规范我们的行为。以我自己的TinyMVC为例,model层完全是我们自己实现的。
  1. /**
  2. * 本model是对discuz uc_client/client.php全局函数的再包装
  3. */

  4. class Discuz_Uc_Model extends TinyMVC_Model {

  5.     private static $cookie_name = null;

  6.     protected static $_global_functions = array();

  7.     public function __construct()
  8.     {
  9.         // 下面两个常量在单入口定义
  10.         include TMVC_MY_UC_API_DIR . 'config.inc.php';
  11.         include TMVC_DISCUZDIR . 'uc_client' . DS . 'client.php';
  12.         
  13.         // if uc cookie name is empty
  14.         if (empty(self::$cookie_name))
  15.             self::$cookie_name = !empty($cookiepre) ?  $cookiepre . $cookiename : $cookiename;
  16.         
  17.         // 收集自定义函数
  18.         $functions = get_defined_functions();
  19.         unset($functions['internal']);
  20.         self::$_global_functions = & $functions['user'];
  21.     }
  22.    
  23.     /**
  24.      * 将discuz uc client 的api函数转为本类方法
  25.      *
  26.      * @access public
  27.      * @param $fun string discuz UCenter API function name
  28.      * @param $args array the params that transmited to $fun
  29.     */
  30.     public function __call($fun, $args)
  31.     {
  32.         if ( in_array($fun, self::$_global_functions) )
  33.         {
  34.             return call_user_func_array($fun, $args);
  35.         }
  36.         else
  37.         {
  38.             throw new Exception("The discuz uc api function '{$fun}' had not found.");
  39.         }
  40.     }
  41.    
  42.     /**
  43.      * 获取我们在uc api中设置的cookiename,解密,返回带用户id和用户名的数组
  44.      *
  45.      * @access public
  46.      * @return array  if $cookie_name is empty return null
  47.      *        array(0=>uid, 1=>username)
  48.     */
  49.     public function fetch_discuz_uc_by_cookie()
  50.     {
  51.         return !empty($_COOKIE[self::$cookie_name]) ? explode("\t", $this->uc_authcode($_COOKIE[self::$cookie_name], 'DECODE')) : array();
  52.     }   
  53.   
  54. }
复制代码
这样,当在controller使用$this->model->uc_user_login()时,实际上是调用uc api的uc_user_login函数,比如上面代码最后的$this->authcode()方法就是调用uc_client/client.php里面的同名函数,使用方法参考官方api。至此,我们就可以随心所欲地在control里面读取ucenter里面的数据。
--完--

评分

参与人数 1贡献 +10 收起 理由
民审-M + 10 赞一个!

查看全部评分

帖子地址: 

回复

举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆 用百度帐号登录 一键登录:

本版积分规则

收藏帖子 返回列表 搜索
快速回复 返回顶部 返回列表