前言
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腳本,交由瀏覽器來處理。
參考: