Java經過UCenter實現Discuz同步登陸

前言
javascript

discuz_ucenter_api_for_java針對UCenter1.5/1.6版本都可正常通訊,測試過程當中,Discuz X2.5/X3.0/X3.2均測試經過。在開始前,有幾個點須要先了解。php

  1. Discuz和UCenter是兩個相對獨立的應用系統,只是通常在安裝Discuz的時候集成安裝了UCenter。html

  2. Discuz和UCenter分別有各自獨立的用戶數據表,Discuz的是`數據庫名`.[前綴]_common_member,Ucenter的是`數據庫名`.[前綴]_ucenter_membersjava

  3. UCenter是一個統一的用戶管理中心,是Comsenz旗下各個產品(Discuz、X-Space、SuperSite等)之間信息直接傳遞的一個橋樑,經過UCenter 站長能夠無縫整合Comsenz系列產品,實現用戶的一站式登陸以及社區其餘數據的交互。web

  4. 在Discuz中註冊用戶,Discuz會將用戶同步到UCenter中。在UCenter中註冊了用戶,不會同步到Discuz。sql

搭建Discuz環境

從Discuz官網下載安裝Discuz程序,安裝過程略。其中數據庫名表名前綴須要記住,在後面建立Ucenter用戶時同步Discuz用戶時要用到。shell

UCenter中註冊應用

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配置的,有的地址是域名配置的,因此確認一下以保證以後的配置的一致性。

配置Java Web應用

下載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腳本,交由瀏覽器來處理。


參考:

http://my.oschina.net/u/1274710/blog/165570

http://my.oschina.net/banbo/blog/311691

相關文章
相關標籤/搜索