上次聊了怎么用"搭积木"的方式搭后台,这次聊聊怎么把积木搭进企业生态——企微集成 + 能力开放平台。
写在前面:后台框架的"孤岛困境"
上一篇《当 90% 的中后台还在重复造轮子》发出后,不少同学在评论区问了一个问题:
"框架内部能力确实全,但企业里不可能只用你一个系统。审批要推到企微,外部系统要调你的接口,这些怎么搞?"
好问题。说实话,这也是我做完低代码、工作流、AI 之后,一直在想的事。
一个后台框架如果只管自己内部那摊事,做得再好也是信息孤岛。
企业真实的长这样:
- 员工日常用企业微信沟通,审批、通知、待办都希望在企微里完成
- 外部 ERP / CRM / 小程序要调你的业务接口,不能每个对接方都给一套账号密码
- 管理员配完企微和开放平台后,自己都不知道配得对不对,得让开发去翻日志
- 企微通讯录一变,本地用户表就脱节了,新员工登不进来,离职员工还在系统里
这些事单独拎出来都不难,难的是每接一个项目都要重来一遍。于是我把企业微信协同和能力开放做进了 Forge,今天聊聊这两块。
先放个演示地址,文章里说的所有东西都能在线试:
www.dlforgelab.com:8084/forge/login (账号 admin / 123456)
一、企业微信集成:不是"扫码登录",是整个协同层
先说最大的误解——很多人以为"企微集成"就是加个企业微信扫码登录。不是。
1.1 多数框架的企微集成长什么样
| 能力 | 多数框架的现状 |
|---|---|
| 登录 | 支持企微扫码,但 OAuth 回调直接把用户信息丢给前端,前端再提交后端 |
| 通讯录 | 手动导入或写一次性脚本同步,人员变动靠人工记得改 |
| 消息 | 自己写企微 API 调用代码,散落在各个业务模块里 |
| 待办 | 企微收不到审批通知,或者收到后点了跳过去是一个没有鉴权的 URL |
| 安全 | Secret 明文存数据库,回调验签全靠自己手写,出了问题不好查 |
核心问题:每加一个平台(飞书、钉钉),这些逻辑全要再写一遍。
1.2 Forge 的做法:先建通用底座,企微只是第一个适配器
我没有把企微逻辑写死在登录、用户、消息、流程这些模块里。而是先做了一层平台无关的企业协同 SPI,企业微信只是它的第一个完整适配器。
架构长这样:
forge-starter-collaboration(通用 SPI 层)
├── Provider Connector 接口 ← 飞书/钉钉以后只需实现这个
├── 能力枚举(LOGIN/DIRECTORY/MESSAGE/TODO)
├── 统一上下文 + Provider Registry
└── 合同测试套件 + Fake Provider ← 证明编排层不依赖企微分支
forge-plugin-collaboration(编排插件)
├── 连接管理(一个租户可配多个企业连接)
├── 应用管理(每个连接下可挂多个物理应用,Secret 只存一份)
├── 通讯录同步(全量 + 增量 + 冲突处理 + 问题单)
├── 消息投递(统一 COLLABORATION 渠道,逐接收人结果)
├── 待办投影(Flowable 任务 → 企微卡片,状态始终以 Forge 为准)
└── 回调收件箱(验签/解密/防重放/去重/异步补偿)
一句话总结:飞书、钉钉后续只需实现 Connector,不动组织同步、消息、待办和运维主链路。
1.3 安全这件事,我花了最多精力
企业集成涉及身份认证、人员停用和流程操作,安全出问题就是大事。几个关键设计:
登录链路彻底重写了 OAuth 流程:
| 环节 | 旧做法(多数框架) | Forge 的做法 |
|---|---|---|
| OAuth state | 前端生成或不校验 | 服务端一次性生成并保存,绑定连接/租户/动作 |
| 回调返回 | 完整 AuthUser 返回前端 | 只返回短期一次性socialTicket,前端拿不到第三方用户信息 |
| 身份来源 | 信任前端提交的 socialUuid | 只认服务端校验过的连接和外部身份 |
| 账号合并 | 手机号/邮箱相同自动合并 | 禁止自动合并,只认通讯录已建立的映射,防止错误合并员工 |
凭据安全:
所有 Secret、Token、Callback Token、EncodingAESKey 全部走版本化 AES-GCM 认证加密存储,管理端只返回"已配置"状态和固定掩码。空值保留(不改不动),轮换用比较更新防并发恢复旧值。认证加密不可用时失败关闭,不回退明文。
待办回调不能越权审批:
企微卡片点击后,Forge 重新校验:外部身份 → 接收人 → 租户 → 任务当前状态 → 办理权限。任务已完成、已撤回或操作者无权时,返回业务已失效并更新外部卡片,不重复执行。
1.4 通讯录同步:不是一次性脚本,是完整运维闭环
| 能力 | 说明 |
|---|---|
| 全量同步 | 读取完整快照 → 校验父子关系 → 分阶段落库 → 成功后才处理未出现记录 |
| 增量处理 | 成员新增/变更/离职/转部门,定时全量校准兜底 |
| 权限边界 | 同步只管本连接拥有的映射,Forge 角色/组织内角色/手工岗位不覆盖 |
| 失败保护 | 拉取中断时不误停用存量人员(这个坑很常见) |
| 问题单 | 冲突、失败进队列,管理员可绑定/忽略/重试 |
| 同步日志 | 批次、阶段、计数、游标、状态全可查 |
"企微是通讯录权威来源,Forge 是权限权威来源" ——这个边界很重要。同步不会误删你手工配的角色和权限。
1.5 管理端:配完就知道行不行
新增了一整套管理界面(演示站可体验):
| 页面 | 干什么 |
|---|---|
| 连接管理 | 配置企业连接,管理登录/通讯录/消息/待办应用,Secret 永不明文返回 |
| 连通测试 | 按能力执行 Token/读取/测试消息验证,配完立刻知道行不行 |
| 同步日志 | 查看同步批次和阶段统计 |
| 问题单 | 冲突/失败队列,可人工处理 |
| 映射查看 | 查看外部部门/成员/岗位/标签与 Forge 的映射 |
| 投递管理 | 消息和待办投递状态,失败可人工重试 |
| 回调事件 | 回调元数据和 processing 状态(不返回解密正文) |
二、统一能力开放平台:把内部能力安全地"开出去"
第二块是能力开放平台。这个更硬核——它解决的是"外部系统怎么安全地调你的接口"。
2.1 为什么要做这个
客户场景很真实:外围系统(ERP、小程序、第三方应用)需要调 Forge 的业务接口——建单、发起审批、查询数据。老做法是给每个对接方开一个账号,写一段鉴权代码,然后在 Controller 里手动校验权限。
问题在哪?
- 没有统一鉴权:每个接口各写各的,漏一个就是越权
- 没有幂等:网络重试就重复建单
- 没有限流:对接方一个循环就把你打垮
- 没有审计:出了问题查不到谁调了什么
- 管理员没法自助:配完授权不知道能不能调,要开发去翻日志
2.2 Forge 的做法:一个网关兜住所有外部调用
核心是一个统一 REST 开放网关:
外部请求
│
├── 1. 认证(OAuth Bearer 或 HMAC-SHA256 签名)
├── 2. 防重放(timestamp ±5分钟 + nonce 一次性校验)
├── 3. 授权(能力是否已发布?客户端是否已授权?)
├── 4. 身份校验(required_actor_type:USER/SERVICE/BOTH)
├── 5. 限流(读 120次/分,写 20次/分,可配置)
├── 6. 幂等(写操作强制 Idempotency-Key,命中返回首次响应快照)
├── 7. Schema 校验(按已发布版本校验请求体)
├── 8. 执行(CapabilityExecutor + ExecutionIdentity 上下文)
├── 9. 统一响应 {code, message, requestId, timestamp, data}
└── 10. 审计入库(不保存请求/响应原文)
这条链路上每一步都是可配置、可审计、可拒绝的。 任何一步不通过,直接返回明确的错误码,不往下走。
2.3 两种认证模式,覆盖主流对接场景
| 模式 | 认证方式 | 身份类型 | 适用场景 |
|---|---|---|---|
| OAuth Bearer | Authorization: Bearer fdu_... | SERVICE 或 USER | 现代对接,支持用户委托 |
| HMAC 签名 | X-Forge-App-Id+timestamp+nonce+signature | 仅 SERVICE | 传统系统对接,不依赖 OAuth |
签名串固定为 appId\ntimestamp\nnonce\nMETHOD\npath\nsha256(body),HMAC-SHA256,常量时间比较。简单、安全、可复制。
关键安全设计: 签名密钥是 KEK 加密可逆存储(因为验签要还原原文),和现有 Bearer 凭据的哈希存储完全分离——不改动现有凭据的安全语义。
2.4 能力注册:三种来源,受控发布
不是什么接口都能开放。能力要先注册、发布、授权,才能被外部调用:
| 能力来源 | 说明 | 安全控制 |
|---|---|---|
| 业务动作(BUSINESS_ACTION) | 低代码业务对象的增删改查 | 按字段白名单过滤 |
| 流程动作(FLOW_ACTION) | 发起流程、提交业务申请、审批 | 强制 USER 委托身份 |
| 系统服务(SYSTEM_SERVICE) | 代码显式注册的服务(如"启动已发布流程") | 管理端不可填任意 URL,只选注册项 |
系统服务是关键设计—— 管理员不能在后台填一个任意 URL 就开放出去。系统服务只能由代码注册,发布时固定流程模型和允许变量,调用者不能指定 modelKey、tenantId、userId 或 initiator。这避免了"把内部接口直接代理出去"的风险。
2.5 调用指南:管理员配完就知道怎么调
这是我花精力最多的地方。以前配完授权,管理员不知道行不行,要开发翻日志。现在:
四步式调用指南:
- 选择客户端 → 展示可调用状态和阻断原因(不返回模糊 403)
- 调用前检查 → 逐条诊断:网关开关、客户端状态、grant 状态、actor/auth/权限
- 契约与示例 → 递归参数表(含中文名称、类型、必填、含义、示例)+ Curl/Java 17 示例
- 在线测试 → 真实走 /oauth2/token + /openapi/v1/capabilities/:code/invoke,有副作用的能力二次确认
认证方式一键切换: OAuth 和 HMAC 示例通过单一选择器切换,URL、能力编码、Header、Body 与真实网关契约完全一致。
文档下载:
- Markdown 调用文档:概述、地址、主体要求、认证、Header、参数表、业务规则、权限、幂等/限流、错误码、OAuth/HMAC 示例、排障——外围开发不用看 Forge 源码就能接入
- OpenAPI 3.1 JSON:可直接导入 Swagger/Apifox
一句话:管理员配完,自己就能判断能不能调、怎么调、为什么不能调。
2.6 身份桥接:外部用户怎么变成 Forge 用户
外部系统调用流程审批类能力时,需要一个真实的 Forge 用户身份。Forge 提供两条路:
| 方式 | 说明 | 适用场景 |
|---|---|---|
| 受信 OIDC Token Exchange | 外围系统提交受信 IdP 签发的 JWT,Forge 按issuer + subject自动映射现有用户并签发短期 USER Token | 有统一身份提供方 |
| 客户端签名用户断言 | 无统一 OIDC 时,客户端用 RSA 私钥签发短期 JWT(最长 2 分钟),Forge 验签后按预绑定sub委托真实用户 | 无统一 IdP |
安全边界很明确:
- 外部 JWT 只接受管理员显式配置的 HTTPS issuer 和 audience,默认不配置即失败关闭
- 只允许 RS256,禁止 none 和共享密钥
- 手机号匹配默认关闭,只有验签 + 防重放 + 格式校验全通过后才允许租户内唯一匹配
- 不为不存在的 Forge 用户自动建号
- 断言和 OIDC 使用不同 subject_token_type,验签失败不互相回退
2.7 审计:每一次调用都可追溯
每次调用(含被拒绝的)写
ai_capability_invocation_log,记录:
requestId / capabilityCode / version / clientId / actorType / actorUserId / tenantId / resultCode / httpStatus / schemaPath / durationMs
不保存: 请求 Body、响应 Body、Token、Secret、签名、Nonce 原文、用户手机号。
控制台可按 requestId 串联:入口接收 → 认证完成 → 授权完成 → 幂等命中 → 执行成功/失败。排障不用翻服务器日志。
三、两块拼在一起:企业集成的完整故事
企微集成和能力开放平台不是孤立的两个功能,拼在一起就是一条完整的企业集成链路:
┌─────────────────────────────────┐
│ Forge Admin │
│ │
企业微信 ───────→ │ 企微协同层 │
(通讯录/登录) │ ├── 人员同步 → sys_user │
│ ├── 安全登录 → Sa-Token 会话 │
│ ├── 消息投递 → 消息中心 │
│ └── 待办投影 → Flowable 任务 │
│ │
外部系统 ───────→ │ 能力开放平台 │
(ERP/小程序/ │ ├── OAuth/HMAC 认证 │
第三方应用) │ ├── 能力注册/发布/授权 │
│ ├── 网关调用 → CapabilityExecutor│
│ └── 审计追溯 → 调用日志 │
│ │
│ 低代码 + 工作流 + AI + 多租户 │
└─────────────────────────────────┘
一个真实场景走一遍:
- 企业微信通讯录同步 → Forge 自动建立用户映射
- 员工在企微收到审批卡片 → 点击安全跳转到 Forge 待办 → 完成审批
- 外部 ERP 系统通过 HMAC 签名调用 Forge 开放接口 → 发起采购审批流程
- 流程审批人通过企微待办完成审批 → 结果回写业务系统
- 全程:内部用户走企微协同,外部系统走能力开放,两套链路各自安全
以前这套东西从零搭,至少一个月。现在配一配,跑通验证,几天就能上线。
四、算笔账:自己搭 vs 用 Forge
| 能力 | 自己从零搭 | 用 Forge |
|---|---|---|
| 企微通讯录同步 | 写同步脚本 + 增量处理 + 冲突处理 ≈ 5 人日 | 配置连接 + 连通测试 ≈ 半天 |
| 企微安全登录 | OAuth + state 校验 + 票据交换 ≈ 3 人日 | 配置连接 + 能力绑定 ≈ 2 小时 |
| 企微消息投递 | 企微 API + 逐人结果 + 重试 ≈ 3 人日 | 统一消息渠道,配置即用 |
| 企微待办卡片 | 任务投影 + 回调 + 鉴权 ≈ 5 人日 | 绑定流程 + 安全跳转 |
| 开放 API 网关 | 认证 + 防重放 + 限流 + 幂等 ≈ 8 人日 | 开启网关 + 注册能力 |
| 客户端授权管理 | 凭据 + 授权 + 审计 ≈ 5 人日 | 控制台配置,开箱即用 |
| 调用文档 | 手写文档 + 维护 ≈ 持续成本 | 自动生成 Markdown + OpenAPI |
| 飞书/钉钉扩展 | 全部重来 ≈ 15+ 人日 | 实现 Connector,不改主链路 |
粗算:自己搭这套企业集成,40-50 人日起步。用 Forge,配置 + 验证,一周内能跑通。
五、说点实在的不足
不吹,客观说几个当前的限制:
- 飞书、钉钉适配器还没做。 通用底座和合同测试已经就位,企微是第一个完整适配器,飞书/钉钉需要后续独立实现——但不用改主编排链路,这是架构上的保证。
- 企微待办的"卡片内直批"默认关闭。 基线只开放"安全跳转到 Forge 查看详情"。客户要启用卡片内同意/驳回,需要额外配置流程白名单和专项 UAT——这是安全取舍,不是技术做不到。
- 需要公网 HTTPS 和企微可信域名。 企微回调要求公网可达的 HTTPS 地址、可信域名/IP 白名单和稳定证书,本地开发需要用内网穿透工具。
- 开放平台默认关闭。 FORGE_CAPABILITY_OPEN_GATEWAY_ENABLED=false,需要显式开启。这是安全设计——不用的能力默认不暴露。
- 作为相对年轻的功能模块, 企微集成的真实大规模 UAT 还在积累中。如果你的企业规模大(几千人以上),建议先在测试企业验证同步性能和回调量级。
六、上手体验
所有文章里说的能力,演示站都可以在线试:
- 后台管理演示:www.dlforgelab.com:8084/forge/login (账号 admin / 123456)企业协同:系统管理 → 企业协同能力开放:开放平台 → 能力目录 / 客户端 / 授权管理 / 调用日志
- 项目文档:www.dlforgelab.com:8084/forge-docs/
源码地址:
- Gitee:gitee.com/ForgeLab/fo…
- GitHub:github.com/yaomindong1…
七、最后聊两句
上篇"搭积木"聊的是怎么把内部能力做扎实。这篇聊的是怎么把这些能力接通企业生态——向内接企业微信,向外开能力网关。
企业后台说到底解决的是三件事:内部管得好、对内能协同、对外能开放。 缺一不可。
做企微集成时最深的感受是:安全边界比功能更重要。 登录不能信任前端身份、通讯录同步不能误删人员、待办回调不能越权审批——这些不是"做了就行",是"做对了才敢上"。所以你在文章里看到大量"失败关闭""禁止自动合并""重新校验"的设计,都是被真实场景教出来的。
做开放平台时最深的感受是:管理员体验决定成败。 网关安全做得再好,管理员配完不知道行不行、开发要翻日志排障,那这个平台就是半成品。所以调用指南、就绪诊断、在线测试、自动文档——这些"体验"功能花的精力不比安全链路少。
开源不易,持续迭代更难。如果觉得有用,点个 Star 是最大的鼓励。
你现在的企业集成方案是什么?企微对接最头疼的是哪块?评论区聊聊,想看哪块源码拆解的也可以扣——
- 扣 1:想看企微通讯录同步的源码拆解(全量快照 + 增量 + 冲突处理)
- 扣 2:想看开放网关安全链路的源码拆解(认证 → 防重放 → 授权 → 限流 → 幂等)
- 扣 3:想看 OAuth state + 一次性票据登录链路的完整拆解
我挑呼声最高的那块下一篇详细写。