java J2EE与DiscuzX3.2的UCenter实现单点登录

最近笔者在实现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里加上     

 

[html]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  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项目中。如果不能翻墙的朋友请到这里下载:《discuz_ucenter_api_for_java.zip》解压后把以下目录的中的全部java源代码放在自己的项目中就行但要注意,上面web.xml中配置的<servlet-class>com.fivestars.interfaces.bbs.api.UC</servlet-class> 要与这里导入包一致。

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

 

[java]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  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对象,并且对其调用相对应的方法就行)

   退出测试代码:

 

[java]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  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。输出页面即可,测试时可以先在浏览器地址栏输入。

 

注册测试代码:

[java]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  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的方法。
        只要用以下方法重载一下就好

[java]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  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方法改成如下

 

[java]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  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());

并把它改成:

[java]  view plain  copy
 
 print?在CODE上查看代码片派生到我的代码片
  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小结(实现与论坛同步登录等操作)》

转载于:https://www.cnblogs.com/zxxyx/p/6211428.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值