前言
javascript
discuz_ucenter_api_for_java针对UCenter1.5/1.6版本都可正常通讯,测试过程当中,Discuz X2.5/X3.0/X3.2均测试经过。在开始前,有几个点须要先了解。php
Discuz和UCenter是两个相对独立的应用系统,只是通常在安装Discuz的时候集成安装了UCenter。html
Discuz和UCenter分别有各自独立的用户数据表,Discuz的是`数据库名`.[前缀]_common_member,Ucenter的是`数据库名`.[前缀]_ucenter_members。java
UCenter是一个统一的用户管理中心,是Comsenz旗下各个产品(Discuz、X-Space、SuperSite等)之间信息直接传递的一个桥梁,经过UCenter 站长能够无缝整合Comsenz系列产品,实现用户的一站式登陆以及社区其余数据的交互。web
在Discuz中注册用户,Discuz会将用户同步到UCenter中。在UCenter中注册了用户,不会同步到Discuz。sql
从Discuz官网下载安装Discuz程序,安装过程略。其中数据库名和表名前缀须要记住,在后面建立Ucenter用户时同步Discuz用户时要用到。shell
UCenter登陆没反应?数据库
我遇到过这个问题,不论是Discuz X2.5仍是X3,安装好Discuz后,正确输入了创令人密码,可是提交后一直没有反应,能够编辑uc_server/model/admin.php,找到约第22行的apache
$this->cookie_status = 0;
改为api
$this->cookie_status = isset($_COOKIE['sid']) ? 1 : 0;
若是你能够正常登陆UCenter,就不用管这个问题了。
从Discuz进入UCenter,在UCenter中的应用管理中添加新应用:
在添加新应用中录入如下相关参数(其它的默认,不用管):
应用类型:其它
应用名称:自定义
应用主url:Java Web应用的访问地址,http://[ip]:[port]/[appname] ,如我在本地Tomcat部署上部署了一个应用,访问地址是:http://192.168.203.128:8080/dzclient4j,注意结尾不要添加“/”(斜杠)
通讯密钥:自定义,用于UCenter和Java Web程序约定的通讯密钥,以后会在Java Web应用中配置一样的密钥。如“java_ucenter”
是否开启同步登陆:是
是否接收通知:建议选“是”
添加成功后,会查看到刚刚添加的应用的ID,这个应用ID待会儿咱们会用到。同时看到通讯状况为通讯失败,这个暂时不用管。
接下来,咱们要将要配置咱们的WEB程序,在配置WEB程序以前咱们先要确认一下UCenter的地址:
由于有的地址是IP配置的,有的地址是域名配置的,因此确认一下以保证以后的配置的一致性。
下载discuz_ucenter_api_for_java应用程序。
将src下的代码复制到本地WEB应用的src下,修改复制过来的config.properties
#UCenterf地址 UC_API = http\://192.168.203.1/bbs/uc_server #UCenter的IP,可为空 UC_IP = #通讯秘钥,与在UCenter注册的通讯秘钥一致 UC_KEY = java_ucenter #应用ID,在UCenter注册应用生成的ID UC_APPID = 2 #该项可为空 UC_CONNECT =
在本地WEB应用的web.xml中添加以下配置:
<servlet> <servlet-name>api</servlet-name> <servlet-class>com.fivestars.interfaces.bbs.api.UC</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>api</servlet-name> <url-pattern>/api/uc.php</url-pattern> </servlet-mapping>
接下来,咱们启动JAVA WEB应用程序,再回到UCenter的应用列表,会发现通讯成功。
如今咱们是以在discuz中能够正常登陆的帐号为例,帐号先不要是中文的。
Client e = new Client(); String result = e.uc_user_login("test", "111111"); LinkedList<String> rs = XMLHelper.uc_unserialize(result); if(rs.size()>0){ int $uid = Integer.parseInt(rs.get(0)); String $username = rs.get(1); String $password = rs.get(2); String $email = rs.get(3); if($uid > 0) { System.out.println("登陆成功"); System.out.println($username); System.out.println($password); System.out.println($email); String $ucsynlogin = e.uc_user_synlogin($uid); System.out.println("登陆成功"+$ucsynlogin); } else if($uid == -1) { System.out.println("用户不存在,或者被删除"); } else if($uid == -2) { System.out.println("密码错"); } else { System.out.println("未定义"); } }else{ System.out.println("Login failed"); System.out.println(result); }
如上代码,登陆成功返回$ucsynlogin的是一个js,直接放到浏览器中去执行,而后,再在浏览器中打开discuz,你会发现已经登陆了。
中文问题参考http://www.cnblogs.com/gaoxing/p/4373937.html
咱们来改造discuz_ucenter_api_for_java。(个人discuz和java web都是utf-8的,若是你的discuz是gbk的,则改为相应的编码来测试一下)
1.删除自带一个Base64的工具类(com.fivestars.interfaces.bbs.util.Base64),咱们引用apache的commons codec包里的Base64类。修改PHPFunctions的base64_decode和base64_encode两个方法。
private Base64 base64 = new Base64(); protected String base64_decode(String input){ try { return new String(base64.decode(input),"iso-8859-1"); } catch (Exception e) { return e.getMessage(); } } protected String base64_encode(String input){ try { return new String(base64.encode(input.getBytes("iso-8859-1"))); } catch (Exception e) { return e.getMessage(); } }
2.修改PHPFunctions类的urlencode方法。
protected String urlencode(String value){ try { return URLEncoder.encode(value,"utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; }
3.修改Client的uc_fopen方法
BufferedReader reader = new BufferedReader(new InputStreamReader(ins,"UTF-8"));
4.修改Clent的uc_authcode方法,主要是将substr($result.toString(), 26)进行转码
if($operation.equals("DECODE")) { String $result = $result1.substring(0, $result1.length()); String temp=substr($result.toString(), 26); try { temp=new String(temp.getBytes("iso8859-1"),"UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } if((Integer.parseInt(substr($result.toString(), 0, 10)) == 0 || Long.parseLong(substr($result.toString(), 0, 10)) - time() > 0) && substr($result.toString(), 10, 16).equals( substr(md5(substr($result.toString(), 26)+ $keyb), 0, 16))) { return temp; } else { return ""; } } else { return $keyc+base64_encode($result1.toString()).replaceAll("=", ""); }
public static void testRegister(){ Client uc = new Client(); String $returns = uc.uc_user_register("王五", "111111" ,"wangwu@test.com" ); int $uid = Integer.parseInt($returns); if($uid <= 0) { if($uid == -1) { System.out.print("用户名不合法"); } else if($uid == -2) { System.out.print("包含要容许注册的词语"); } else if($uid == -3) { System.out.print("用户名已经存在"); } else if($uid == -4) { System.out.print("Email 格式有误"); } else if($uid == -5) { System.out.print("Email 不容许注册"); } else if($uid == -6) { System.out.print("该 Email 已经被注册"); } else { System.out.print("未定义"); } } else { System.out.println("OK:"+$returns); } }
如上代码,经过Java向UCenter中注册了一个新用户。返回的$returns值是新建UCenter用户的ID。
不过咱们如今只是在UCenter中注册了用户,如今直接经过Java去登陆Discuz是登陆失败的,须要先在Discuz页面去登陆一次后,才能够从Java正常登陆Discuz。这个缘由主要是,咱们经过Java注册用户,只是在UCenter中注册了,而并无在Discuz中注册用户,因此第一次登陆需要从Discuz登陆,从Discuz登陆的时候会发现没有这个用户,可是在UCenter中是认证经过的,因而便提示,是否要在Discuz中激活这个新建的用户。
好了,如今我要作的就是在注册UCenter用户的时候,也同步在Discuz中注册用户,直接在Discuz的用户表中插入数据。修改uc_server/model/user.php,大概在138行(不一样版本的discuz可能有所差别),function add_user 函数里添加代码:
function add_user($username, $password, $email, $uid = 0, $questionid = '', $answer = '', $regip = '') { $regip = empty($regip) ? $this->base->onlineip : $regip; $salt = substr(uniqid(rand()), -6); $password = md5(md5($password).$salt); $sqladd = $uid ? "uid='".intval($uid)."'," : ''; $sqladd .= $questionid > 0 ? " secques='".$this->quescrypt($questionid, $answer)."'," : " secques='',"; $this->db->query("INSERT INTO ".UC_DBTABLEPRE."members SET $sqladd username='$username', password='$password', email='$email', regip='$regip', regdate='".$this->base->time."', salt='$salt'"); $uid = $this->db->insert_id(); $this->db->query("INSERT INTO ".UC_DBTABLEPRE."memberfields SET uid='$uid'"); // BEGIN $this->db->query("INSERT INTO ".DISCUZ_DBTABLEPRE."common_member SET uid='$uid', username='$username', password='$password', email='$email', adminid='0', groupid='10', regdate='".$this->base->time."', credits='0', timeoffset='9999'"); $this->db->query("INSERT INTO ".DISCUZ_DBTABLEPRE."common_member_status SET uid='$uid', regip='$regip', lastip='$regip', lastvisit='".$this->base->time."', lastactivity='".$this->base->time."', lastpost='0', lastsendmail='0'"); $this->db->query("INSERT INTO ".DISCUZ_DBTABLEPRE."common_member_profile SET uid='$uid'"); $this->db->query("INSERT INTO ".DISCUZ_DBTABLEPRE."common_member_field_forum SET uid='$uid'"); $this->db->query("INSERT INTO ".DISCUZ_DBTABLEPRE."common_member_field_home SET uid='$uid'"); $this->db->query("INSERT INTO ".DISCUZ_DBTABLEPRE."common_member_count SET uid='$uid', extcredits1='0', extcredits2='0', extcredits3='0', extcredits4='0', extcredits5='0', extcredits6='0', extcredits7='0', extcredits8='0'"); // END return $uid; }
注意这些表都是 Discuz 的表,不是 UCenter 的表,不能使用 UC_DBTABLEPRE ! UCenter 配置文件 uc_server/data/config.inc.php 中定义了 DISCUZ_DBTABLEPRE:
define('DISCUZ_DBTABLEPRE', '`bbs`.pre_');
bbs是数据库名称,pre是安装discuz时指定的前缀。
public static void testLogout(){ Client uc = new Client(); String $ucsynlogout = uc.uc_user_synlogout(); System.out.println("退出成功"+$ucsynlogout); }
既出的代码很简单,相似于同步登陆,返回的$ucsynlogout也是一个javascript脚本,交由浏览器来处理。
参考: