最近笔者在实现Java项目对discuz的整合。在此过程中,查了很多这方面的资料,发现网上并没有说得比较全面的文章。笔者博取众长以及自己在此过程中遇到的问题,写下来供大家参考,希望大家可以在这过程中少走弯路。笔者在此过程中主要参考了https://code.google.com/p/discuz-ucenter-api-for-java/后,感谢作者ping china.大家可以到此下载接口。

第一步:写好你的配置文件config.properties。(把这个文件放J2EE工程的源路径下就行)     
 UC_API = http://你的discuz地址/uc_server  如http://10.238.11.11/forum/uc_server
 UC_IP = 正常情况下留空即可
 UC_KEY = 123456(与ucenter通信的密钥,这里自己设定,需与discuz ucenter一支)
 UC_APPID = 2  
 UC_CONNECT = 正常情况下留空即可
第二步:在你的web.xml里加上

  1. <!-- servlet 'disuz_uc_api' 用于接收Discuz UCenter的同步消息, 此项配置必须有。(可适当调整 load-on-startup参数) -->
  2. <servlet>
  3. <servlet-name>disuz_uc_api</servlet-name>
  4. <servlet-class>com.fivestars.interfaces.bbs.api.UC</servlet-class>
  5. <load-on-startup>2</load-on-startup>
  6. </servlet>
  7. <servlet-mapping>
  8. <servlet-name>disuz_uc_api</servlet-name>
  9. <url-pattern>/api/uc.php</url-pattern>
  10. </servlet-mapping>

<servlet-class>com.fivestars.interfaces.bbs.api.UC</servlet-class>如果是直接把使用的UC类放在自已的项目中类包名应该根据自已的包名修改。

<url-pattern>/api/uc.PHP</url-pattern>(这里一定要配置成/api/加上Ucenter中的接口文件名一样,如果J2EE项目中用了权限控制工具如shiro,记得把你的/api/uc.php开放成无需登录也能访问的url)

第三步:配置ucenter.

以管理员身份登录-》管理中心-》ucenter-》应用管理。

填写以下信息:应用名称:你的应用的名称

通信密钥:你刚在config.properties的UC_KEY (123456)

是否开启同步登录:是

是否接受通知:是

其他的留空即可。

如下图所示:

如果出现以下情形,则Ucenter与J2EE项目联接完成:

通信不成功记得查看你的权限的问题,查看http://ip:<port>/{project}/api/uc.php是否未登录可以访问,因为我们的项目中用了shiro对权限进行控制

http://ip:<port>/{project}/api/uc.php未登录是不能访问的,一直通信失败也是找了好久才找到错误的原因。

下面是J2EE对Discuz的同步登录测试:(如果在要测试这一步,只需要把以上第一步和第二步完成后就可以测试,不用Ucenter与J2EE通信成功)

然后我们先试一下登录,以下是测试代码。(到这里还不支持中文,后面会提到)

首先要将里的源代码或者jar导入J2EE项目中。如果不能FQ的朋友请到这里下载:《discuz_ucenter_api_for_java.zip》解压后把以下目录的中的全部java源代码放在自己的项目中就行但要注意,上面web.xml中配置的<servlet-class>com.fivestars.interfaces.bbs.api.UC</servlet-class> 要与这里导入包一致。

然后就可以java代码就调用以下的方法就可以完成功能了:

  1. public static String login(String userName,String pwd){
  2. Client e = new Client();
  3. String result = e.uc_user_login(userName, pwd);
  4. String $ucsynlogin = "";
  5. LinkedList<String> rs = XMLHelper.uc_unserialize(result);
  6. if(rs.size()>0){
  7. int $uid = Integer.parseInt(rs.get(0));
  8. String $username = rs.get(1);
  9. String $password = rs.get(2);
  10. String $email = rs.get(3);
  11. if($uid > 0) {
  12. $ucsynlogin = e.uc_user_synlogin($uid);
  13. } else if($uid == -1) {
  14. System.out.println("用户不存在,或者被删除");
  15. } else if($uid == -2) {
  16. System.out.println("密码错");
  17. } else {
  18. System.out.println("未定义");
  19. }
  20. }else{
  21. System.out.println("Login failed");
  22. System.out.println(result);
  23. }
  24. return $ucsynlogin;
  25. }

建一个测试类,把这个方法加进去,然后调用此方法,传参数值用户名和密码,然后返回的是一个string。string的内容是一段js代码。

js代码如下:

<script type="text/JavaScript" src="http://10.238.18.80:8181/api/uc.php?time=1456454359&code=21a8EQSq6G3mCzbecik4DxlsNWfm0icW44qGLPgcnC2N5QyPfu0EtDpkZJ8xMjFSWVhOwJhxwBJCuCDOFTL6YWkYQgelDp5OzqGmqNpJ3CVqw2Eh4xm2IOO2uoVDzxBFWlXGmTWRAamNmHzPbiylTg6fXnvcRA9T0ihk" reload="1"></script>

只要把这段js代码输出到页面上去就实现了discuz那边的登录了。你可以先试试把这段js输入到浏览器的地址栏。只要把红色的url复杂到浏览器访问,然后访问Discuz的首页就可以看到相应的用户已经登录了。(下面包括注册以及登出啊,原理都是一样,只要创建Client对象,并且对其调用相对应的方法就行)

退出测试代码:

  1. public static String logout(){
  2. Client uc = new Client();
  3. String $ucsynlogout = uc.uc_user_synlogout();
  4. System.out.println("退出成功"+$ucsynlogout);
  5. return $ucsynlogout;
  6. }

此方法也是返回一段js。输出页面即可,测试时可以先在浏览器地址栏输入。

注册测试代码:

  1. public static void reg(String userName, String password, String email) {
  2. Client uc = new Client();
  3. String $returns = uc.uc_user_register(userName, password ,email);
  4. int $uid = Integer.parseInt($returns);
  5. if($uid <= 0) {
  6. if($uid == -1) {
  7. System.out.print("用户名不合法");
  8. } else if($uid == -2) {
  9. System.out.print("包含要允许注册的词语");
  10. } else if($uid == -3) {
  11. System.out.print("用户名已经存在");
  12. } else if($uid == -4) {
  13. System.out.print("Email 格式有误");
  14. } else if($uid == -5) {
  15. System.out.print("Email 不允许注册");
  16. } else if($uid == -6) {
  17. System.out.print("该 Email 已经被注册");
  18. } else {
  19. System.out.print("未定义");
  20. }
  21. } else {
  22. System.out.println("OK:------------------------"+$returns);
  23. }
  24. }

到这里,还只是实现了java项目登录后论坛那边能自动登录。但论坛那边登录了,java这边还没登录。

因为我们本身的系统的用户名只能是手机号码,所以关于中文的问题没有测试过,这里复制过来,也只是为了整个问题解决方案的完整性。有需要的朋友自行测试。

别急,我们先解决一下中文用户名的问题,其实这个问题https://code.google.com/p/discuz-ucenter-api-for-java/里已经提到了,并提供了解决方案。感谢原作者。但我还是啰嗦一下,因为我感觉说的不够详细,大家可能要花去你的宝贵时间去了解。解决方法如下:

在PHPFuctions.java里有一个名叫urlencode的方法。
        只要用以下方法重载一下就好

  1. protected String urlencode(String value,String code){
  2. try {
  3. return URLEncoder.encode(value,code);
  4. } catch (UnsupportedEncodingException e) {
  5. // TODO Auto-generated catch block
  6. e.printStackTrace();
  7. }
  8. return null;
  9. }

并把Client.java里的uc_api_input方法改成如下

  1. public String uc_api_input(String $data) {
  2. String $s = urlencode(uc_authcode($data+"&agent="+md5("")+"&time="+time(), "ENCODE"            , UC_KEY),"GBK");
  3. return $s;
  4. }

好!java中文登录问题解决了。

下面是Discuz那边登录,J2EE方面也登录的解决方法,这里就需要前面做换Ucenter和J2EE的通信成功才能完成以下测试了:

我们来看看discuz那边登录了,java这边怎么实现同步登录。

在UC.java里有一个doanswer的方法。所有同步操作都在这个方法里完成。

其逻辑是这样的,UC这个类继承了HttpServlet。

当ucenter发出通知时,会访问这个servlet.并执行他的doGet()方法。doGet()调用doAnswer().

String $code = request.getParameter("code");

会传一个code进来(加密了的)。

然后调用$code = new Client().uc_authcode($code, "DECODE");进行解密操作。

新建一个Map,Map<String,String> $get = new HashMap<String, String>();

然后根据解密出来的code的内容封装这个Map.

调用这个方法,parse_str($code, $get); 经过以上操作后,所有同步操作需要的信息都在map里,如action。

action代表的是什么操作,如同步登录,同步退出,修改密码等。还有其他信息,如username.登录的用户名。

改密码时还会传新密码过来。所有的这些都包含在这个叫$get的Map里。然后我们就可以进行我们自己的逻辑操作了。

(以上逻辑不想理解没关系,你只要知道当你在discuz登录之后,uc.java的doAnswer()方法就会被调用,你所需要的一切信息都包含在$get这个Map里)

操作到这里,你一定想吐槽笔者!不行啊,discuz那边登录了,java这边完全没反应啊!!doAnswer方法没有被调用啊!是的,你还需要到discuz后台做一些设置。

管理中心->站长->ucenter设置。把ucenter连接方式改为接口方式。然后,你登录discuz时,doAnswer()方法就会被调用了。(其他操作如退出也一样)

到这里,我们又遇到了中文的问题了,discuz用中文登录的时候不行啊!是的,这确实是个比较麻烦的问题。

笔者也弄了好久。原因是这样的:

上面提到过,传进来的$code是需要uc_authcode()方法进行解密的,当中文的时候解密出来的$code是"".解决方法如下:在Client.java的uc_authcode()方法里找到这句String $result = $result1.substring(0, $result1.length());

并把它改成:

  1. String $result= $result1.toString();
  2. try{
  3. $result=new String($result.getBytes("iso-8859-1"),"GBK");
  4. }catch (Exception e) {
  5. $result = $result1.substring(0, $result1.length());
  6. // TODO: handle exception
  7. }

这样还不行,解密出来的code中文部分仍是乱码。

所以在uc.java的$code = new Client().uc_authcode($code, "DECODE");这句下面还要加上$code = new String($code.getBytes("GBK"),"UTF-8");

可能有人会说直接转成utf-8不行吗?为什么要先转成gbk呢?如果直接转成utf-8的话,解密出来的$code是""。

到此中文的问题就得到解决了。笔者下载的是GBK版本的discuz,其他情况自己改一下编码应该没问题。

至此,只要我们在doAnswer()方法里添加我们自己的逻辑代码就已经能实现java和discuz的同步了。

另外,有个问题提醒大家,就是在discuz那边修改密码的时候,ucenter并不是马上发出通知的,这可能会引起同步和安全的问题。

文章转载自:《java整合discuz小结(实现与论坛同步登录等操作)》

java J2EE与DiscuzX3.2的UCenter实现单点登录的更多相关文章

  1. ucenter的单点登录

    所谓单点登录,无非就是几个站点共用一个用户中心,实现同步登陆,同步退出. 服务器端:Loog SSO . 客服端: ucenter,说实话dz商业化确实让php发展了不少. ucenter 基本原理: ...

  2. 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...

  3. Yii整合ucenter实现单点登录

    原文:http://www.php2.cc/article-1349-1.html 准备工作 1.下载ucenter源码,并安装好 2.下载ucenter开发源码,根据自己的项目下载对应版本(utf- ...

  4. java集成微软的ad域,实现单点登录

    1.ad域介绍: windos server 2008R2服务器下的ad域,见下图(我是在虚拟机安装到windos server) 2.连接ad域代码:(里面代码自行修改) public Result ...

  5. Java架构师必知:什么是单点登录,主要会应用于哪些场景?

    单点登录在大型网站里使用得非常频繁,例如,阿里旗下有淘宝.天猫.支付宝,阿里巴巴,阿里妈妈,阿里妹妹等网站,还有背后的成百上千的子系统,用户一次操作或交易可能涉及到几十个子系统的协作,如果每个子系统都 ...

  6. java和Discuz论坛实现单点登录,通过Ucenter(用户管理中心)

    标题有点问题,没有进行修改. 一 Discuz论坛搭建步骤 1:服务器环境配置 服务器要支持php语言+支持mysql 5.0以上的数据库 + Apache服务器(支持网站的一个服务器,通过域名的能访 ...

  7. UCenter在JAVA项目中实现的单点登录应用实例

    Comsenz(康盛)的UCenter当前在国内的单点登录领域占据绝对份额,其完整的产品线令UCenter成为了账号集成方面事实上的标准. 基于UCenter,可以将Comsenz旗下的Discuz! ...

  8. 点单登录原理和java实现简单的单点登录

    引用自:http://blog.csdn.net/zuoluoboy/article/details/12851725 摘要: 单点登录(SSO)的技术被越来越广泛地应用到各个领域的软件系统当中.本文 ...

  9. 单点登录与消息队列以及在J2EE中的实现方案

    前言 这次为大家简单介绍两个在WEB开发中经常使用的概念——单点登录和消息队列以及具体到J2EE中的一些实现方案.本文原创性的工作比较少,主要是一些总结概括和自己的理解. 单点登录SSO SSO的业务 ...

随机推荐

  1. 转载:详细解析Java中抽象类和接口的区别

    在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制.正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力.abstract class和int ...

  2. AMBA

    基于IP复用的设计方法在SOC设计中得到了广泛的应用,设计过程中,片上总线的设计师最关键的问题. AMBA是由ARM公司退出的片上总线,是一种流行的工业标准片上结构. AMBA规范主要包括了AHB(A ...

  3. About SSDT BI

    Welcome to Microsoft Marketing Speak hell. With the 2012 release of SQL Server, the BIDS, Business I ...

  4. 利用ffmpeg给小视频结尾增加logo水印

    背景 1.app有类似微信拍摄小视频功能,时长上限8s,视频文件保存在第三方云存储,app直接上传,后端数据库只记录视频的存放地址. 2.最近一次功能迭代,增加了小视频下载功能,小视频有可能在别的社交 ...

  5. GraphicsMagick+Im4Java在windows和linux下的配置

    GraphicsMagick介绍及安装 Im4Java包为: im4java-1.2.0.jar 直接在lib下引用即可 GraphicsMagick的安装如下: windows下: 安装:Graph ...

  6. Can't connect to MySQL server on localhost (0)

    配置双主的时候,由于一台始终连不上另一台. 于是我使用root账号远程登录查看,填入账户密码点击连接,结果就提示这样的错误. 一开始以为是权限的问题,于是就授与所有权,结果还是报一样的错. 重新创建一 ...

  7. python(29)强大的zip函数

    zip函数:它是python的内建函数,(与序列有关的内建函数有:sorted().reversed().enumerate().zip()),其中sorted()和zip()返回一个序列(列表)对象 ...

  8. ERROR actor.OneForOneStrategy: org.apache.spark.SparkContext

    今天在用Spark把Kafka的数据往ES写的时候,代码一直报错,错误信息如下: 15/10/20 17:28:56 ERROR actor.OneForOneStrategy: org.apache ...

  9. 坦克大战,看你能坚持几秒 ~~Duang~~Duang

    闲来无事,写了一个坦克大战的小游戏,打开页面就能看到源码,代码还没有来得及整理.大家闲来玩玩吧,看谁玩的时间长! http://xiaohaibaomu.com/home/index

  10. I prefer fcitx

    sudo add-apt-repository ppa:fcitx-team/nightly sudo apt-get update Then, you should install Fcitx.Fc ...