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

相关文章
相关标签/搜索