java整合discuz小结(实现与论坛同步登录等操作)

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

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

        第一步:写好你的配置文件config.properties。     

        UC_API = http://你的discuz地址/uc_server  如http://localhost/forum/uc_server
        UC_IP = 正常情况下留空即可
        UC_KEY = 123456(与ucenter通信的密钥,这里自己设定,需与discuz ucenter一支)
        UC_APPID = 2
        UC_CONNECT = 正常情况下留空即可

        第二步:在你的web.xml里加上        

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

          

        第三步:配置ucenter.

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

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

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

        是否开启同步登录:是

        是否接受通知:是

        其他的留空即可。

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

        

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static String login(String userName,String pwd){
        Client e = new Client();
        String result = e.uc_user_login(userName, pwd);
        String $ucsynlogin = "" ;
  
        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 ) {
                 $ucsynlogin = e.uc_user_synlogin($uid);
             } 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);
         }
         return $ucsynlogin;
     }

    建一个测试类,把这个方法加进去,然后调用此方法,传参数值用户名和密码,然后返回的是一个string。string的内容是一段js代码。只要把这段js代码输出到页面上去就实现了discuz那边的登录了。你可以先试试把这段js输入到浏览器的地址栏。

    退出测试代码:

      

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

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

    注册测试代码:

     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void reg(String userName, String password, String email) {
      Client uc = new Client();
      String $returns = uc.uc_user_register(userName, password ,email);
      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项目登录后论坛那边能自动登录,但论坛那边登录了,java这边还没登录。别急,我们先解决一下中文用户名的问题,其实这个问题https://code.google.com/p/discuz-ucenter-api-for-java/里已经提到了,并提供了解决方案。感谢原作者。但我还是啰嗦一下,因为我感觉说的不够详细,大家可能要花去你的宝贵时间去了解。解决方法如下:

        在PHPFuctions.java里有一个名叫urlencode的方法。

        只要用以下方法重载一下就好        

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

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

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

        好!java中文登录问题解决了。我们来看看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
2
3
4
5
6
7
String $result= $result1.toString(); 
    try
       $result= new String($result.getBytes( "iso-8859-1" ), "GBK" );
     } catch (Exception e) { 
        $result = $result1.substring( 0 , $result1.length()); 
        // TODO: handle exception 
     }

这样还不行,解密出来的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小结(实现与论坛同步登录等操作))