Java Spring Boot 项目与 Discuz! 论坛同步登录登出 会员打通 discuz-ucenter-api-for-java
我的主站 Spring Boot 与 Discuz! 论坛进行了打通,实现了同步的登录登出,并可以将 Discuz! 论坛中会员的数据回显到我的主站中,并且我对之前开源的 discuz-ucenter-api-for-java 进行了部分修改,以适应当下 Spring Boot 的风格。
首先鸣谢开源
与 Discuz! 打通一般分为通过 API 通讯和数据库通讯,这次介绍的是通过 API 通讯,这就不得不提一下 discuz-ucenter-api-for-java,首先要感谢原作者:梁平 (no_ten@163.com)将他的代码开源,这让我们节省了很多时间。
重新修改开源代码
在我下载源码后我发现这个还是2009年的代码,满满的复古风,而且原作者是根据PHP的代码翻译过去的,所以里面很多习惯并不是Java的习惯,关键还要配置 servlet,也不支持Maven构建。这在现在的 Spring Boot 项目中是格格不入,所以我对源码进行了修改并二次发布。
为了适应 Maven 构建的 Spring Boot 风格,项目地址:https://github.com/renfei/discuz-ucenter-api-for-java,我做了以下修改:
- 将项目包发布到 Maven 中央仓库
- 基于现在Java的JDK8,移除了原作者的Base64实现,使用JDK8提供的java.util.Base64,所以最低需要JDK8来运行。
- 将方法名下划线的风格改为驼峰命名风格,例如将「uc_user_delete()」改为「ucUserDelete()」。
- 将PHP风格的变量名改为普通Java用的变量名,例如将「String $module」改为「String $module」。
- 将使用配置文件的方式改为实例化时构造方法传参的方式
- 将配置 servlet 改为自行定义 Controller 并处理 HttpServletRequest 和 HttpServletResponse
- 部分中文乱码的问题进行了修复
Discuz的UCenter配置
在开始集成前,我们先要对Discuz的UCenter进行配置,拿到接口地址、通讯Key、APPID。先到Discuz的后台UCenter这里,新增一个应用:

然后填写配置,应用类型选择“其他”,再个应用起个名字,应用主的URL地址就填你的地址,通信秘钥自己随便设置个密码,最下方选择开启同步登录和接受通知:

Spring Boot 集成 discuz-ucenter-api-for-java
我使用的是 Maven 构建的 Spring Boot 项目,所以需要先修改 pom.xml 将 discuz-ucenter-api-for-java 引入项目中:
<dependency>
<groupId>net.renfei</groupId>
<artifactId>discuz-ucenter-api-for-java</artifactId>
<version>1.0.6</version>
</dependency>
然后我个人认为分为两大部分,一部分是作为客户端进行接收来自Discuz的UCenter的消息;一部分是主动向Discuz的UCenter发送消息,我们分开来说。
接收来自Discuz的UCenter的消息
先创建一个Controller,然后创建一个处理HttpServletRequest和HttpServletResponse的方法,给一个UCenter请求的地址@RequestMapping("/api/uc.php"),实例化一个客户端net.renfei.discuz.ucenter.api.UCClient和net.renfei.discuz.ucenter.client.Client,然后把HttpServletRequest交给net.renfei.discuz.ucenter.api.UCClient.doAnswer()去处理,最后将结果写入HttpServletResponse,如果UCenter配置正确,就应该可以在UCenter看到通讯正常了。具体使用如下案例:
@Controller
public class UCenterController {
@ResponseBody
@RequestMapping("/api/uc.php")
public void uc(HttpServletRequest request, HttpServletResponse response) throws IOException {
UCClient ucClient = new UCClient();
Client client = new Client("http://localhost:8080/uc_server", null, "123456789", "3","");
String result = ucClient.doAnswer(client, request, response);
response.getWriter().print(result);
}
}
主动向Discuz的UCenter发送消息
注册
Client client = new Client("http://localhost/uc_server", null, "key", "2","");
String string = client.ucUserRegister("username","password","email");
先登陆再同步登陆
Client client = new Client("http://localhost/uc_server", null, "key", "2","");
// 登陆
String result = client.ucUserLogin(uid);
LinkedList<String> rs = XMLHelper.ucUnserialize(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) {
//同步登陆
String string = client.ucUserSynlogin(uid);
//本地登陆代码
//TODO ... ....
} 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);
}
登陆
Client client = new Client("http://localhost/uc_server", null, "key", "2","");
String string = client.ucUserLogin("username","password");
同步登陆
Client client = new Client("http://localhost/uc_server", null, "key", "2","");
int UID = 21; //此处是用户的UID
String string = client.ucUserSynlogin(uid);
常见问题
同步登陆接口成功但没有登陆状态
- 症状表现:调用 net.renfei.discuz.ucenter.client.Client#ucUserSynlogin 成功,拿到了JavaScript代码,请求JS地址也成功,但是访问Discuz就是没有登陆状态。查看请求JS地址的Response头信息,Set-Cookie中没有xxxx_2132_auth的Cookie。
- 发现场景:首先调用 net.renfei.discuz.ucenter.client.Client#ucUserRegister 进行用户注册,然后调用 net.renfei.discuz.ucenter.client.Client#ucUserLogin 用户登陆获取 uid,再调用 net.renfei.discuz.ucenter.client.Client#ucUserSynlogin 进行同步登陆获取 JavaScript代码,浏览器请求JS地址,全部都是成功状态,但是访问Discuz就是没有登陆状态。
- 问题根源:当调用 net.renfei.discuz.ucenter.client.Client#ucUserRegister 进行用户注册后,用户信息会在 UCenter 中注册插入 pre_ucenter_members 表中,但不会自动插入 Discuz 论坛的 pre_common_member 表中,所以调用 net.renfei.discuz.ucenter.client.Client#ucUserSynlogin 进行同步登陆成功,访问 Discuz 的时候因为 Discuz 中没有这个用户的信息,所以不会有登陆状态。
- 解决方案:第一种:注册用户的逻辑直接连接数据库,将用户相关的数据插入 UCenter 和 Discuz 的用户相关表中,涉及到的表需要查文档这里不再赘述。第二种:修改 UCenter 的代码,在插入 UCenter 用户表的同时,向 Discuz 用户表中也同步插入用户的信息。
- 最后总结:UCenter 只是中间桥梁,打通各个应用的用户账号,但它不会通知各个应用有了新用户,Discuz 自带的登陆页面登陆的时候发现自己没有这个用户就会从 UCenter 拉取这个用户信息插入自己的用户表,所以你通过 UCenter 注册接口注册用户以后,如果这个用户从未登陆过 Discuz,那么 Discuz 中是没有这个用户的信息的,如果你想统一登陆验证,那么就需要你手动到 Discuz 的用户表中插入相关信息,其中涉及到多个表,请查阅官方文档。
更多信息请阅读源代码,此处不再一一演示。您可以提出issues或者到我的社区论坛一起讨论:https://bbs.renfei.net/forum-44-1.html
商业用途请联系作者获得授权。
版权声明:本文为博主「任霏」原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接及本声明。
相关推荐
猜你还喜欢这些内容,不妨试试阅读一下评论与留言
以下内容均由网友提交发布,版权与真实性无法查证,请自行辨别。- 2023-04-28 11:10:43
- Beijing, Beijing, China
- 回复
- 2023-04-28 11:17:18
- Beijing, Beijing, China
- 回复
- 2020-12-29 14:20:43
- Beijing, Beijing, China
- 回复
微信订阅号
扫码关注「任霏博客」微信订阅号- 大佬 引入jar包那里的 driver class 怎么选的?
- 我也遇到了这个问题,已经解决了,在此分享一下 1、宿主机也要创建kingbase的用户和用户组,并且要查看一下用户和用户组的ID(这个很重要) 2、把data目录的用户和用户组设置为kingbase 3、先不要把data路径挂载到宿主机上,这时就可以正常启动,启动后进入容器,查看一下容器内的kingbase的用户和用户组ID是多少,和第一步的ID是否一致,如果ID一致,那正常挂载目录就行;如果ID不一致,那就需要修改Dockerfile文件,在构建镜像时,修改容器内的用户和用户组ID,必须和宿主机的保持一致。然后重新构建镜像,就可以正常挂载宿主机目录了 4、其实直接修改宿主机的用户和用户组ID也是可以的,但是容器内的ID一般是1000,但是宿主机的这个ID很可能已经被占用了,无法修改,就只能修改容器内的ID
- 接口已经允许跨域请求,也就是说你可以在你的页面上调用,获取用户的公网 IP。 如果你还需要其他需求,可以提交 Issue 给我。
- V008R003C002B0320 这个对应的jdbc链接驱动你在哪里找到的?我也遇到了这个问题。
- WARNING: max_connections should be less than orequal than 10 (restricted by license) HINT: the value of max_connect is set 10 WARNING: max_connections should be less than orequal than 10 (restricted by license) HINT: the value of max_connect is set 10 kingbase: superuser_reserved_connections must be less than max_connections 我按照文档修改了以后,不知道如何重启。
- 然后把数字都改成 1 再启动。 如何重新启动?
- ksql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/tmp/.s.KINGBASE.54321"
- 进入容器查看一下日志,是不是启动失败了,日志文件在:/opt/kingbase/logfile
- ksql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/tmp/.s.KINGBASE.54321"?
- 先通过 docker exec -it 容器名/id /bin/bash 进入容器,然后在容器中使用 ksql 客户端进行连接数据库:/opt/kingbase/Server/bin/ksql -U system test
- 免费.ml域名10年委托合同到期被马里共和国收回域名经营权
- 从极狐Gitlab看各种中间件技术选型
- 时隔十年首次收到 Google AdSense 的付款
- ga域名被加蓬共和国从Freenom公司手中收回域名经营权
- Freenom 被 Meta(Facebook) 起诉导致暂停 .tk/.ga/.ml/.cf/.gq 等新域名注册
- 生花妙笔信手来 – 基于 Amazon SageMaker 使用 Grounded-SAM 加速电商广告素材生成 [1]
- github.renfei.net 不再完整代理 Github 页面改为代理指定文件
- 优雅的源代码管理(三):本地优雅的使用 Git Rebase 变基
- 优雅的源代码管理(二):Git 的工作原理
- 优雅的源代码管理(一):版本控制系统 VCS(Version Control System)与软件配置管理 SCM(Software Configuration Management)