ThinkSNS与Ucenter整合

上回我写过一点thinksns与ucenter整合的注意事项,详情可见:thinksns在整合Ucenter的时候注意事项,今天我写的另外的一些注意点。

上回仅仅是做UCAPI接口的通讯以及同步登录和退出,因此完全没有涉及到系统模块。今天我要讲的是,如何修改系统自带的login,logout,register,changepwd以及后台的管理。

如果你将login,logout,register都交由第三方来托管,那么,本文的前几段你几乎可以忽略掉。仅看最后的changepwd以及后台管理的注意事项。

OK,让我们开始吧。判断是否登录,我这里不管了,请看我上篇文章吧。。

【注意】由于加载uc_client,会导到错误发生,原因查看:THINKPHP框架与Ucenter通讯注意事项,因此,我在thinksns的define.inc.php中,强行定义了uc_connect为空,这是一个常量,在这里定义后,在uc_config文件中又定义了一次。会出现一个notice,这个我们不用管。常量是不会被覆盖的。之所以这样做,我是有理由的。thinksns在整合Ucenter的时候注意事项一文中我说过,uc.php没有用到任何thinkSNS除api外的核心函数,因此也就没有加载THINKPHP框架,所以不会有THINKPHP框架与Ucenter通讯注意事项文中所说的base类的冲突。而我们现在涉及的则是在thinksns内部使用uc_client,那就不得不先定义uc_connect模式了。正是基于常量不会被覆盖,所以uc_config文件,就不需要被修改了。【方法有点野蛮,但我想应该可以接受】

1、login,系统的login和dologin函数都在IndexAction.class.php中,因此,改起来比较方便,但是需要动/public/themes/中的apps.html模版,因为登录框在这个文件中。没办法,不改不行,uc不支持email登录,所以不得不把email改为username。然后在dologin方法中,直接调用接口,判断用户是否存在,如果不存在则返回错误,存在的话就登录。登录时还要判断,如果该用户在thinksns库中没有记录,则生成一条记录,用户信息由uc_get_user取回来。同时设定active为1,代表是已激活用户。然后就是原始的登录流程,生成session生成cookie之类的了

2、logout,除了系统标准的logout外,还需要调用一下uc_user_synlogout,以便向其他应用发向退出系统的请求

3、register,如果属于偷懒情况,你可以把register引用到别的应用中【我是自己定义了一个user应用来接管所有的,注册、登录、退出的,所以1、2这些问题,其实我都可以忽略掉】

4、changepwd,这是在用户信息管理界面中的。主要问题也就在这里。如果你不改程序,那你会在这里吐血,因为如果你的用户是通过ucenter过来的,那么password并非标准的md5(password),它的password是有salt的【salt你可以看一下ucenter表。不想多解释】,因此chagepwd功能,你必须得完全改掉。判断原始密码是否正确,也必须先用uc_get_user获取用户的信息后,把获取回来的密码与提交过来的原始密码比对。更改密码时也需要用uc_user_edit进行修改【其实可以两步并一步,因为uc_user_edit的第二个参数就是oldpassword,如果oldpassword不正确,会返回错误代码的,也可以少做一步】,更改完后,就是一个比较重要的一步:把你刚才设置的newpassword,重写回thinksns数据库,可能你会认为是多余的,因为很明显,我们前面的操作都是直接读写ucenter的用户资料,根本没有涉及到本地thinksns用户数据库,为什么还要写回密码?这其实是因为下面的第5步

5、管理,如果你是新安装thinksns,那么或许你不会遇到我说的问题,但如果你是已经安装好,而迁移过来的thinksns,你会发现,你永远登录不了管理界面,为啥?因为你登录前台时的密码是发给ucenter的,而登录后台时,密码是thinksns本地的。因此,你必须得通过changepwd功能先修改一下密码,然后才能操作【所幸管理员不多,这样的问题也都还能够被接受。】

好了,写了这么多,也很累了。如果你遇到问题,也可以咨询我,或者在这里留言。希望本文能够给你带来帮助。

本文首发在这里,明后天会转到我自己的勃客上去,我的勃客地址为:http://www.neatstudio.com,或者你也可以通过http://www.neatcn.com进行访问。

THINKPHP框架与Ucenter通讯注意事项

这其实是一个老问题,凡是使用ThinkPHP与Ucenter通讯的程序都需要注意一点。。

ThinkPHP定义了一个基类为Base类,而Ucenter也同样定义了一个基类Base类。
ThinkPHP一开始就加载了BASE类,而Ucenter在使用mysql连接的的时候,就会加载BAse类。因此,凡是使用thinkphp的程序,请把ucenter的连接方式从mysql改为空,即,改用post方式通信 。

Over

其实,关于这个BUG,我很早就在discuz论坛提过了。当然也在ThinkPHP论坛提过。但事实上,都没有什么解决方案。而我更推崇的应该是ucenter进行变化。。呵呵

【官方】不小心删除了UC文件夹后的处理方法

这是一篇来自官方的教程,原帖地址为:http://www.discuz.net/thread-1477395-1-1.html

有不少用户反映,在整理空间时常常会有不小心删除掉UC文件夹的情况发生。
如果只是删除了UC文件夹,数据库里的数据还在的话,可以通过下面的方法解决:

1、拷贝一份安装好的UC的程序文件,然后修改里面的配置文件,上传到自己的空间上。

2、重新安装UC,注意安装的时候选择跟以前的UC不同的前缀,以免覆盖数据。安装完后,修改UC的配置文件,改成以前的数据的前缀。

3、在数据库中通过工具(如phpmyadmin等)备份UC数据,然后重新安装UC后,导入数据。

以上的方法只能恢复UC使用和会员的注册信息等数据,会员上传的头像等是保存在UC的data\avatar文件夹中的,删除了文件夹就不能恢复了,只能够让会员重新上传。

PS:如果连同UC的数据库一起删除掉了,而且还没有备份的话,就只能重头再来了,所以在平时的使用中一定要注意及时备份,以免丢失站点最重要的会员数据。

thinksns在整合Ucenter的时候注意事项

thinksns在整合ucenter的时候难度并不大。主要有几个思路,不要错过就行了

1、不要想着把thinkphp框架整合进去,那样只会让你效率大低
2、合理应用thinksns提供的API,在API里面有取得当前登录用户的资料等信息,而且也有一个比较完整的数据库操作类【主要是不需要再调用config等配置了】

3、利用ucenter整合的时候,只能利用thinksns的一个cookie: remembor【开始为了这个我折腾了半天,我一直都打成remember。。。。汗一下先】(由于现在我是在一台机器上试,对于$_SERVER['USER_AGENT']是否一致还没有完全测试。。。)

4、整合的两个重要环节就是同步登录和退出。登录的时候要注意一下,两边的密码机制不一样,第一次同步资料的时候需要注意一下,否则一旦整合就不能使用原来的密码了。

5、同步登录的时候,如果需要强制注册,则必须要调用$api->user_add($data)这样的方法,具体的变量参数可以参考 thinksns的lib中的indexAction.class.php ,顺便说一下,它的代码,注册中的隐私,其实没有插数据库。。。。骗子啊

6、起初的时候,我考虑需要读系统配置,就调用了$api->option_get()结果出错,由于ucenter api的出错是不显示的。调试了半天,才发现。原来是option_get()调用的get方法中,居然有一个ts_cache函数,而这个函数却是在 api的范围之外,即它是属于thinksns的common方法中,在api中并没有被包含进来。。导致无法执行出错。

其他就没啥了。。至于feed同步啥的,则需要一点点的测试和更新,以同步到thinksns的feed库中。是个劳心劳力的过程。

首发:http://www.neatstudio.com

UCenter与其他语言的整合经验归纳

1、UCenter建议使用GBK版本,原因是PHP4/5对UNICODE(UTF-8)的支持不足,分解出来的数字与其他支持UNICODE的语言不同,以至于authcode的时候将出现偏差,非拉丁文本将不匹配,即导致中文用户名无法正常同步。但其他语言的API可以使用UTF-8,再在 authcode之前将文本转换成GBK即可。

2、Java下有一个UCenter的API,可以较方便的在Java环境下调用UCenter接口,地址是 http://code.google.com/p/discuz-ucenter-api-for-java/,创始人是ping.china。 Snow_Young也有重新开发一个API的想法,以更符合Java的开发习惯,同时希望可以找到途径以解决UTF-8的问题。

3、登入、登出等操作的同步,使用post方式调用UCenter的API接口,如果成功,将返回一段代码,其代码输出到页面将达到跨域请求各应用,应用获得请求后自行进行cookie或session的操作。

4、注册等非同步操作,将不会自动进行同步操作,其他应用在调用数据前应先检查UCenter时候存在更新信息,并将更新信息同步到自身数据库中。例如注册操作,如果用户在例如Java端注册,那么Java端将告诉UCenter注册信息,UCenter将信息存入UCenter数据库中,此时将不进行同步。之后若用户在Discuz!论坛登陆,Discuz!首先将查看自身数据库,若没有,再去请求UCenter获得更新信息,并询问用户是否激活,待用户确认后,才将用户的资料写入Discuz!论坛数据库中。

5、关于UCenter的接口,请下载或直接在线访问Discuz!论坛UCenter开发区置顶帖的API文档。

6、UCenter API文档中函数的调用方法:

integer uc_user_register(string username , string password , string email [, integer questionid , string answer])

以此为例,将函数名分解为user和register,我们可以调用UCenter的index.php,post内容为:

m : user
a : register
release : 1.5
inajax : 1(此参数若不存在,将出现一个跳转div,仅限PHP,所以在此处随意赋上一个值即可)
appid : 3(此为其他语言应用在UCenter中的id)
input : 将所有附加参数的键值对Map经过authcode之后得到的加密字符串

调用完后,此函数将返回注册信息(是否成功、错误原因)的数字。然后我们这里switch一下后采取各种策略。

7、不知是否是bug,或者是特意设计成这样的,Discuz!新注册用户会自动登陆,但却不会进行同步,即不通知其他应用,我建议还是通知一下比较好,呵呵,至少我的应用是这么做的,用户在我这里注册,然后转到Discuz!后,已经进入待激活状态,非常方便。

maxInteger、暂时总结这么多,日后发现还会继续补充,希望大家可以共同完善。

来源:http://sny7.javaeye.com/blog/484502

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

手头上有一个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居然也弄错,希望官方能仔细检查。

以上是修复uc通信与同步登录的个人的一些看法和意见,请大家多多指教。

本文来源:http://www.discuz.net/thread-1367305-1-1.html

【官方】UC备份时出现“无法访问到该应用的备份接口”错误的解决方法

在UC后台进行备份时,经常有人会遇到下面的问题:
备份提示:无法访问到该应用的备份接口,请拷贝 UCenter 根目录下api/dbbak.php 到该应用的api目录下

这种情况有两种解决办法:
一、按照错误提示,把UCenter 目录下的 api/dbbak.php 拷贝到备份出现错误的应用中,相应的 api 目录下

二、如果(一)的方法不好用,请检查一下程序的安装端口是否为80端口,如果是非80端口,也有可能会出现上述问题
此时的解决方法是:
找到UCenter目录下的model/misc.php
把其中两处的

$out .= “Host: $host\r\n”;

改成

$out .= “Host:$host:$port\r\n”;

然后再重新备份。

本文来自官方:http://www.discuz.net/thread-1384475-1-1.html

【官方】UC的验证码不显示或显示异常的问题

UC登陆时需要输入验证码,经常有会员反应站点的验证码不显示或显示异常
在遇到验证码显示的问题时,可以从以下几个方面排查一下

1、查看一下UC目录下的 images\fonts\en 目录下是否存在TTF字体文件;images\gif 目录下是否存在 GIF 字体图
这些文件是产生验证码文字的必要原素,如果发现缺失,请拷贝原始安装文件中的相关文件到相应的目录中

2、查看一下php信息中是GD库信息,如下图:

GD库基本信息

GD库基本信息

UC中正确显示验证码的必要条件是,保证GD库中以下四个支持已安装。

1. GIF Read Support         enabled
2. GIF Create Support         enabled
3. JPG Support         enabled
4. PNG Support         enabled

本文来自官方论坛:http://www.discuz.net/thread-1387893-1-1.html

康盛系列中同步登录的注意事项

康盛目前的产品基本上都使用了ucenter,甚至一些已经卖掉的产品中也有使用ucenter的,比如Ecmall等。

其实很多时候你会发现,你明明在A系统中登录了。但是却没有登录到B系统。这其中有一部分是网页在跳转的时候,代码没有来得及执行完毕导致,但也有一部分是因为这几个系统中的接口有点小小的问题。

现在,我们来还原一下问题产生的情景。

1、到论坛注册一个用户,登录。理论上,这时候康盛所有的产品应该都能够登录了,因此这个注册用户已经在ucenter的用户表中了。

2、打开supesite,你会发现,他会提示您需要登录。再打开uchome,也是如此的提示。一个冷冰冰的登录窗口依然显示在那里。

3、打开ecmall,你会发现,咦,怎么登录了?真奇怪啊。为什么有两个系统没有登录,一个系统登录了?

4、现在,我们重新一一登录supesite和uchome。然后退出系统。再在论坛登录,你会发现,咦。怎么都登录了?原来显示登录窗口的supesite和uchome都已经登录了,这是什么呢?

5、现在我们打开这两个系统的接口仔细分析一下,同时再打开这两个程序的登录程序。突然间,你就恍然大悟。原来这两个系统在登录的时候,都会有一个判断,如果该系统自身的用户表里没有这条记录,那么他们都会先判断用户是否存在,如果确实存在,则往自身的用户表里插入一条记录。然后再进行登录。

6、然而这两个系统的接口文件uc.php中的同步登录函数中,却没有这一条。而只是仅仅的判断是否存在session库中,来判断是否登录。supesite中还会注册一个activetyuser这样一个cookie,以期你在打开supesite的时候,如果有这个cookie就自动插入一条记录【然而,这只是虚晃一枪,根本就没有执行过】

7、再回首,我们看一下ecmall,人家写的就简单了。同样的原理,生成一个cookie,在打开页面时,如果有cookie存在,就生成用户【它是确确实实执行了】。

现在明白问题所在了吧?知道这些问题,你其实可以自己在这个同步登录的函数里加上相应的代码就行了【这里就不写了,看官们,自己练练手吧】

最后再说一点小问题,这个其实说的是uchome,uchome除了用户名密码登录外,还有一个自定义问题。所以即使你同步登录了,但如果设置了自定义问题,进入uchome的时候,还是需要再回答一下这个自定义问题。

Over,全部解释完毕。

白话介绍:客户软件如何与ucenter通讯

如果你写了一个WEB程序,你又想与ucenter共用一个用户库,你会怎么做?

来吧,让我告诉你,只要几个简单的步骤就行了。

1、先到ucenter administrator建一个应用,在应用里配置完你的项目的地址,在UC_KEY那里随便输入一些字符串,越长越好。【在这里有配置通讯文件的名称,好象是提示你在api目录下,你可以定义一个,默认是uc.php】。然后你会一直发现应用列表中,该应用一直是通讯失败。

2、生成应用后,在应用详情的最下方有一个textarea框,这个就是系统帮你生成的连接ucenter的配置文件 。

3、在您的项目根目录下建立一个api目录,里面放上刚才说的通讯文件,默认是uc.php

在通讯文件里定义一些常量,可以从uchome、supesite、等里面拷贝出来,其实就是一些返回值 的常量。

加载刚才ucenter administrator所生成的配置文件。

到comsenz的任何一个程序中拷贝一下authcode函数(一般在common.inc.php或者global.inc.php中)

写上简单的判断代码:

$code = $_GET['code'];   //取得GET回来的code变量

//经过authcode解码后,转化为一个数组,这个数组里其实就有一些简单的验证信息,如:时间,传递过来的操作等
parse_str(authcode($code, ‘DECODE’, UC_KEY), $get);

//如果当前时间大于传递来的时间1小时,返回超时
if(time() – $get['time'] > 3600) {
exit(‘Authracation has expiried’);
}

//如果转换出来的$get变量是空值 ,那肯定是出错了
if(empty($get)) {
exit(‘Invalid Request’);
}

//获取传递过来的操作
$action = $get['action'];

//写上一个简单的判断
if ($action == ‘test’){
exit(API_RETURN_SUCCEED);
}

4、写完这样的代码后,去ucenter管理中心看一下应用列表,是不是通讯成功了?

其实那个通讯成功,就是发送了一个 action = test过来。所以当返回1的时候就直接成功了。

不过,由于exit();函数自身的状态,如果参数是字符串,则会直接输出,而如果参数是整数,则仅仅用来表示退出程序,而整数则代表了error code。

If status is an integer, that value will also be used as the exit status. Exit statuses should be in the range 0 to 254, the exit status 255 is reserved by PHP and shall not be used. The status 0 is used to terminate the program successfully.

这时候,你就会发现,你必须得使用exit(“1″);才会真正的输出1。【当然,这是PHP的基础,与通信问题不大,在这里提出来,只是为了防止你明明写了exit(1),却不会输出而在那里拼命调试】

OK,到现在为止,一个简单的通讯就完成了。如果你需要更多的功能,可以参考一下server究竟提供了哪些服务,然后写上针对性的代码和判断就可以了。

本文没图,但我相信,说的应该够明白了吧?