第三方系统集成到 V-IM Pro 的实现方案

11 阅读14分钟

第三方系统集成到 V-IM Pro 的实现方案

很多团队在接入 IM 能力时,真正的诉求并不是“再造一套用户、组织和登录体系”,而是让现有业务系统直接复用 IM 能力。

从当前 v-im-server-pro 仓库的实现来看,V-IM Pro 走的并不是“单体大而全”的路线,而是拆成了两层能力:

  • 一层是 OAuth2 授权服务,用来解决第三方系统如何安全接入、如何换取用户身份。

  • 一层是 Bridge 业务桥接,用来解决第三方系统原有的用户、部门、密码、头像等数据如何映射到 V-IM。

这篇文章结合当前仓库中的真实代码,介绍第三方系统集成到 V-IM Pro 的推荐实现方案,并说明为什么 v-im-server-ry-plus 不是一个单纯的 OAuth2 客户端示例,而是一个“宿主业务系统适配层”的实现样板。


一、先说结论:V-IM Pro 的接入方案不是只配几个参数

如果只看接入文档,很容易把这件事理解成“给第三方系统配置一个 client_idclient_secretcallback_url 就结束了”。

但从代码上看,完整接入实际上分成 3 个层面:

  1. OAuth2 服务端层

V-IM Pro 负责签发授权码、访问令牌,并对外提供用户信息接口。

  1. 业务桥接层

第三方系统原本的 sys_usersys_dept、密码体系、租户字段,需要通过桥接层映射为 V-IM 可识别的统一用户模型。

  1. 客户端落地层

第三方系统自己的前端回调页、后端换 token 逻辑、OpenID 绑定逻辑,需要在业务系统里补齐。

所以,第三方系统接入 V-IM Pro,推荐采用下面这套思路:

  • V-IM Pro 作为统一 IM 能力中心和 OAuth2 授权中心。

  • 第三方业务系统 保留自己的账号体系、组织架构和业务菜单。

  • 通过 Bridge + OAuth2 的组合,把“登录接入”和“组织/用户同步”拆开治理。

这也是当前仓库最值得借鉴的地方。


二、当前仓库里,各模块分别扮演什么角色

从根 pom.xml 可以看到,当前工程由 4 个模块组成:

  • v-im-server

  • v-im-server-ry-plus

  • v-im-server-plugin

  • v-im-server-mcp

如果只讨论第三方系统集成,重点是前三个模块。

1. v-im-server:IM 核心能力

v-im-server 提供 IM 核心服务、登录服务、用户信息接口以及 Sa-Token 的基础认证能力。

例如在 com.vim.modules.login.service.impl.VimLoginServiceImpl 中,登录与注册最终都会委托给 VimBridgeService

  • 登录时调用 vimBridgeService.login(loginParam)

  • 注册时调用 vimBridgeService.register(registerParam)

这说明 V-IM Pro 的核心层并不强依赖某一种用户体系,而是把“用户从哪里来”这个问题交给桥接层解决。

2. v-im-server-plugin:OAuth2 与插件能力

第三方系统接入的关键代码在这个模块里。

其中最核心的几个类是:

  • com.vim.plugin.oauth2.controller.SaOAuth2ServerController

  • com.vim.plugin.oauth2.service.impl.SaOAuth2TemplateImpl

  • com.vim.plugin.oauth2.service.impl.ImOauthClientServiceImpl

  • com.vim.plugin.oauth2.service.impl.ImOauthUserServiceImpl

这一层负责:

  • 暴露 /oauth2/authorize/oauth2/token 等 OAuth2 标准接口

  • 从数据库表 im_oauth_client 读取客户端配置

  • 校验回调地址与授权范围

  • 生成并维护 OpenID 与用户的映射关系

  • 通过 /oauth2/userinfo 对外输出用户资料

3. v-im-server-ry-plus:第三方业务系统桥接样板

很多人会误以为这个模块是“RuoYi Plus 的 OAuth2 客户端”。

但从代码上看,它真正做的是另外一件事:把 RuoYi Plus 的用户/部门体系桥接进 V-IM Pro。

核心实现类是:

  • com.vim.common.bridge.VimBridgeServiceImpl

  • com.vim.common.bridge.ImSettingBridgeService

  • com.vim.plus.domain.SysUser

  • com.vim.plus.domain.SysDept

这层做了几件关键事情:

  • 直接读取外部业务库中的 sys_usersys_dept

  • 转换为 V-IM 内部使用的 UserDept 结果对象

  • 对接外部系统的密码校验逻辑

  • 处理注册、头像、IM 设置等差异化能力

换句话说,v-im-server-ry-plus 解决的是“第三方系统的数据如何进入 V-IM”,而不是“第三方系统如何调 V-IM 的 OAuth2 接口”。


三、为什么 V-IM Pro 要用“OAuth2 + Bridge”两层架构

这是当前实现方案最合理的地方。

如果只做 OAuth2,能解决的是“第三方系统如何在 V-IM 完成授权并拿到身份凭证”,但解决不了下面这些问题:

  • V-IM 如何识别第三方系统里的用户、部门、手机号、邮箱

  • V-IM 登录时如何复用外部系统原有密码

  • V-IM 如何读取外部系统组织架构

  • V-IM 如何在不重建用户中心的前提下完成用户资料映射

如果只做桥接,不做 OAuth2,又会带来另外几个问题:

  • 第三方系统没有统一标准化授权协议

  • 接入多个业务系统时,认证流程不一致

  • 前端回调、授权确认、Token 换取缺少统一入口

因此,当前仓库采用的是更适合企业落地的组合:

  • Bridge 解决数据与账号体系复用

  • OAuth2 解决标准化授权接入

这个架构很适合下面几类系统:

  • OA、ERP、CRM、工单系统

  • 已有 RuoYi / Spring Boot 后台系统

  • 已经维护了独立组织架构与用户库的业务平台


四、OAuth2 服务端在 V-IM Pro 中是如何实现的

1. OAuth2 能力开关

v-im-server/src/main/resources/application.yml 中,Sa-Token 已开启 OAuth2 Server 能力:

  • enable-authorization-code: true

  • enable-password: true

  • enable-client-credentials: true

这意味着 V-IM Pro 已经具备 OAuth2 服务端能力。

对于第三方系统接入,最推荐的仍然是 authorization_code 授权码模式,因为它最适合前后端分离系统,也更容易控制安全边界。

2. OAuth2 请求入口

SaOAuth2ServerController 中,@RequestMapping("/oauth2/*") 把 OAuth2 标准请求统一交给 SaOAuth2ServerProcessor 分发。

这意味着像下面这些接口,本质上都走的是 Sa-Token OAuth2 服务端能力:

  • /oauth2/authorize

  • /oauth2/token

  • /oauth2/refresh

除此之外,当前项目又额外扩展了两个很实用的接口:

  • /oauth2/userinfo

  • /oauth2/getRedirectUri

其中:

  • /oauth2/userinfo 用于第三方系统拿到 access_token 后,按 Authorization: Bearer 方式获取用户资料。

  • /oauth2/getRedirectUri 用于前端先判断“当前用户是否已登录、是否还需要授权确认”,再决定是否直接跳转。

3. 客户端信息如何管理

第三方系统在 V-IM Pro 中不是写死的,而是保存在 im_oauth_client 表中。

管理入口在 ImOauthClientController

  • POST /vim/plugin/oauth2/client

  • PUT /vim/plugin/oauth2/client

  • DELETE /vim/plugin/oauth2/client/{id}

  • GET /vim/plugin/oauth2/client

新增客户端时,ImOauthClientServiceImpl.add 会自动生成:

  • clientId

  • clientSecret

并保存:

  • clientName

  • clientLogo

  • callbackUrl

  • scope

这套设计的好处是,V-IM Pro 天然支持多客户端接入,不需要每增加一个系统就改代码。

4. 回调地址与授权范围校验

SaOAuth2TemplateImpl.getClientModel 中,V-IM Pro 会从 im_oauth_client 读取当前客户端的:

  • clientSecret

  • callbackUrl

  • scope

然后转换成 Sa-Token 需要的 SaClientModel

这一步很关键,因为它决定了:

  • 哪些回调地址是合法的

  • 哪些 scope 可以被申请

  • 当前客户端允许使用哪些授权模式

也就是说,第三方系统不是“只要拿到 client_id 就能随便跳回任意地址”,而是必须命中 V-IM 后台登记过的 callback_url


五、OpenID 在这套方案里承担什么职责

很多第三方集成失败,并不是失败在 token 换取,而是失败在“拿到身份后,如何建立本地用户映射”。

从当前仓库实现看,V-IM Pro 对 OpenID 提供了两层能力:

  1. SaOAuth2DataLoaderImpl.getOpenid

当前直接走 Sa-Token 默认算法生成 OpenID。

  1. ImOauthUserServiceImpl.saveOauthUser

当前仓库额外提供了 im_oauth_user 持久化能力,便于把 clientIduserIdopenId 的关系落库。

也就是说,V-IM Pro 的思路很明确:

通过 clientId + userId 生成稳定的 openId,并在需要时把这层映射关系持久化。

其中 ImOauthUserServiceImpl.saveOauthUser(String clientId) 的逻辑是:

  1. 使用 openid-digest-prefix + clientId + loginId 计算 openId

  2. 检查 im_oauth_user 中是否已存在映射

  3. 如果不存在,则保存 clientIduserIdopenId

这套设计有几个优点:

  • 同一个用户在不同客户端里可以有不同的 OpenID

  • 第三方系统只需要保存 openId,不需要暴露 V-IM 内部用户主键

  • 后续做账号绑定、解绑、单点登录扩展时,都有稳定标识可以使用

所以从集成角度看,openId 不是附属字段,而是第三方系统与 V-IM 建立身份映射的核心锚点。


六、v-im-server-ry-plus 给第三方系统接入提供了什么参考

如果把 OAuth2 看作“怎么进来”,那 v-im-server-ry-plus 更像是在回答“进来以后怎么接到现有业务数据上”。

1. 用户桥接

VimBridgeServiceImpl 中最核心的工作,是把外部系统的 SysUser 转换成 V-IM 需要的 User

例如它会做这些映射:

  • userId -> id

  • nickName -> name

  • userName -> loginName

  • phonenumber -> mobile

  • deptId / email / sex 直接透传

这意味着第三方系统不需要重建一套 V-IM 用户表,只要能提供稳定的用户主键和基础资料,就能被桥接进来。

2. 部门桥接

同样,SysDept 也会被转换为 V-IM 的 Dept 结果对象,映射字段包括:

  • deptId -> id

  • deptName -> name

  • parentId

  • leader -> masterId

  • ancestors -> parentIds

这说明 V-IM Pro 在设计上默认支持“复用第三方系统现有组织架构”。

3. 登录桥接

VimBridgeServiceImpl.login(LoginParam loginParam) 会:

  1. 从第三方系统用户表查询账号

  2. 校验密码

  3. 校验停用状态

  4. 调用 StpUtil.login(sysUser.getUserId())

  5. 返回 V-IM Token

这里的关键不是登录逻辑本身,而是它说明了一件事:

V-IM Pro 并不要求第三方系统把密码迁移进 IM 库,而是允许桥接已有认证逻辑。

4. 注册与默认资料初始化

register(RegisterParam registerParam) 则展示了另外一个很常见的集成需求:

如果第三方系统允许用户从 IM 侧完成注册,桥接层需要负责:

  • 生成业务侧用户 ID

  • 写入外部 sys_user

  • 初始化默认 IM 设置

  • 生成默认头像

同时 RegisterAspect 还在注册后自动给新用户加管理员好友。

这说明桥接层不仅能做“读映射”,也能做“写回外部系统”的联动。


七、第三方系统真正的接入流程,应该怎么走

结合当前文档与代码,推荐流程如下。

第一步:在 V-IM Pro 中注册第三方客户端

由管理员在 V-IM Pro 中创建 OAuth2 客户端,生成:

  • client_id

  • client_secret

并登记:

  • 客户端名称

  • 回调地址 callback_url

  • 授权范围 scope

对应的数据最终落在 im_oauth_client 表。

第二步:第三方系统前端准备回调页

第三方系统需要有一个真实可访问的页面路由,例如:

  • /oauth2-login

这个页面的职责不是直接登录,而是:

  1. 读取 V-IM 跳回来的 code

  2. 调用第三方系统自己的后端接口

  3. 由后端再去请求 V-IM 的 /oauth2/token

这一点在接入文档里已经写得很清楚:

callback_url 是客户端页面地址,不是 V-IM 服务端地址。

第三步:第三方系统后端拿授权码换 Token

后端用下面这些参数请求 V-IM:

  • grant_type=authorization_code

  • code

  • client_id

  • client_secret

目标地址是:

  • {server-url}/oauth2/token

这里的 server-url 必须是 V-IM OAuth2 服务端根地址,而不是客户端自己的回调地址。

第四步:使用 Access Token 拉取用户信息

第三方系统后端拿到 access_token 后,再请求:

  • {server-url}/oauth2/userinfo

并通过请求头传:

  • Authorization: Bearer <access_token>

当前 SaOAuth2ServerController.userinfo() 已经明确按 Bearer Token 方式取值,不再建议通过查询参数传递令牌。

第五步:第三方系统完成本地账号绑定

拿到用户信息后,第三方系统一般有两种处理方式:

  • 如果本地已经有与 openId 对应的账号,直接建立本地登录态

  • 如果没有绑定关系,展示绑定页,让用户把 V-IM 身份映射到本地账号

这也是为什么我前面说,真正稳定的集成一定是“OAuth2 + OpenID 绑定”,而不是只换一次 token 就结束。


八、这套方案最适合什么样的第三方系统

从当前代码结构看,V-IM Pro 更适合接这两类系统。

1. 已有完整账号与组织体系的业务系统

例如:

  • RuoYi Plus

  • 企业 OA

  • 内部 ERP

  • 客服 / 工单 / 审批平台

这类系统已经维护了:

  • 用户表

  • 部门表

  • 登录认证

  • 菜单权限

最适合走桥接方案,不建议再把用户体系复制一份到 IM。

2. 需要把 V-IM 当作统一消息能力中心的平台

比如多个业务子系统都想接统一 IM、统一单点登录,那么:

  • 每个系统在 V-IM 中注册一个 OAuth2 Client

  • 用户体系通过 Bridge 统一接入

  • 多系统共享 V-IM 的消息与在线状态能力

这比每个系统都单独造一套聊天模块稳定得多。


九、落地时最容易踩的几个坑

1. 把 callback_url 配成后端接口地址

这是最常见的问题。

callback_url 应该是浏览器能直接打开的前端页面地址,而不是 Java Controller 地址。

2. 把 server-url 配成客户端地址

server-url 是第三方系统访问 V-IM OAuth2 接口的根地址。

如果写成客户端自己的域名,最终拼出来的 /oauth2/token 一定是错的。

3. 只做 Token 换取,不做 OpenID 绑定

这样会导致:

  • 多次授权无法稳定识别本地账号

  • 后续解绑、换绑、跨系统登录都难以维护

4. 没有明确“谁是主用户库”

当前仓库给出的答案其实很明确:

V-IM 可以不做主用户库,而是通过 VimBridgeService 读取宿主系统数据。

这对于已有业务系统是更现实的方案。

5. 忽略租户字段

v-im-server-ry-plus 的桥接实现中,SysUserSysDept 都带有 tenantId,并且默认按 000000 过滤。

如果你的第三方系统是多租户的,桥接层一定要先设计好租户隔离规则,再谈接入。


十、我对这套实现方案的评价

如果从工程落地角度看,当前 V-IM Pro 的第三方接入方案有三个明显优点。

1. 标准协议和业务适配分层清晰

OAuth2 负责标准化授权,Bridge 负责适配业务系统数据。

这比把所有逻辑都塞进一个登录接口里更容易扩展,也更适合多系统接入。

2. 对现有业务系统侵入较低

第三方系统不需要推翻现有用户库,只需要:

  • 在 V-IM 注册 OAuth2 Client

  • 提供回调页

  • 实现后端换 token

  • 维护 OpenID 绑定关系

如果还要更深度集成,再补 Bridge 即可。

3. 适合逐步演进

企业系统接入 IM 很少一步到位。

先做 OAuth2 单点登录,再做组织架构桥接,再做注册写回、头像映射、租户隔离,是更符合真实项目节奏的演进方式。


十一、推荐的实施顺序

如果你准备把第三方系统接入到 V-IM Pro,我建议按下面顺序推进:

  1. 先打通 V-IM OAuth2 服务端能力

确保 /oauth2/authorize/oauth2/token/oauth2/userinfo 可用。

  1. 再注册第三方客户端

配好 client_idclient_secretcallback_urlscope

  1. 第三方系统补回调页与后端换 token 逻辑

先让授权码模式跑通。

  1. 设计 OpenID 与本地账号绑定关系

不要等上线后再补。

  1. 最后再评估是否需要接入 Bridge 层

如果要复用用户、部门、登录、注册、头像,就按 v-im-server-ry-plus 的方式做适配实现。


十二、总结

第三方系统集成到 V-IM Pro,表面上看是一个 OAuth2 接入问题,实际上是一个“认证授权 + 用户体系复用 + 组织架构映射”的组合问题。

当前仓库给出的答案可以概括成一句话:

v-im-server-plugin 解决标准化 OAuth2 接入,用 v-im-server-ry-plus 这类桥接模块解决宿主系统的数据复用问题。

如果你的系统已经有成熟的用户中心和组织架构,这套方案比“把所有用户重新导入一套 IM 账户体系”更稳,也更符合企业级集成的实际场景。

从工程实践角度看,这也是 V-IM Pro 当前最值得借鉴的一部分设计。