给 MCP Server 加上企业级认证:一次 SSO 接入实践

背景与目标 我们团队维护一个内部数据服务,管实验数据的查询、文件和报告,最近在做的事情是把它暴露成 MCP Server,让 agent 直接查数据、下载文件、导出报告。 工具写完只是一个开始。这个服务里的数据涉及部门和委托公司,不是随便谁都能看的,所以认证和权限必须先解决。企业内部有现成的单点登录服务(下文简称 SSO),最终目标是:用户在 agent 平台里点一次登录,走 SSO 完成认证,之后 MCP 工具调用自动带上身份,数据权限对齐既有系统的语义。 这件事在 9 月于测试环境全链路跑通了。这篇文章记录协议原理、实现拆解和踩过的坑,协议部分和语言无关,换技术栈也能照着做。 主流架构:MCP 授权是什么设计 先说结论:MCP 的授权规范复用了 OAuth 2.0,把 MCP Server 定位成受保护资源(Resource Server),而不是授权服务器。你的 server 从头到尾不碰密码、不发 token、不管理会话,只做一件事:校验请求头里的 Bearer JWT。 我们这次的完整架构长这样: ┌─────────┐ 登录+授权(PKCE) ┌─────────┐ ①授权码流(OAuth客户端) ┌─────────────┐ │ Browser │ ───────────────> │ SSO │ <───────────────────── │ agent 平台 │ │ (用户) │ <─ 302 code 回调 │ (OIDC) │ ②JWT access token │ (连接服务) │ └─────────┘ (平台固定回调) └────┬────┘ ③token托管/自动续期 └──────┬──────┘ │ │ ⑤下发连接 │ ④ JWKS 公钥(server拉取缓存) ▼ ▼ ┌────────────────────────────────────────────────┐ │ MCP Server(任意技术栈) │ │ ⑥ 收 Bearer JWT → 本地验签 → 工具级数据权限 │ └────────────────────────────────────────────────┘ 流程分解一下: ...

September 24, 2026 · 后端开发 / AI · 3 min · 602 words · map[email:onetick@live.cn name:Hongyu]

踩坑实录:ONLYOFFICE forcesave 的同步化处理

背景 最近在做一个在线文档协作系统,用户可以在平台上编辑文档,编辑完成后触发一系列业务流程——生成版本、数字签名、归档等。文档编辑器选用了 ONLYOFFICE,功能强大,协作体验也好。 看起来是个挺常规的需求,对吧? 我当初也是这么想的。直到系统上线后,用户反馈"数字签名偶尔会失效",我才意识到自己踩进了一个不大不小的坑里。 问题出在哪? ONLYOFFICE 的架构中,文档编辑和文件存储是分离的。用户在编辑器里修改文档,改动先停留在 ONLYOFFICE Document Server 的内存中,并不会立即写入你的存储后端。 ONLYOFFICE 提供了 forcesave 接口,可以强制保存文档。我最初的实现是这样的: // 用户点击"提交"按钮时触发 public void submitDocument(String documentId) { // 1. 调用 forcesave onlyofficeService.forceSave(documentId); // 2. 获取文件内容 byte[] fileContent = storageService.getFile(documentId); // 3. 生成数字签名 String signature = signService.sign(fileContent); // 4. 保存签名记录 recordService.saveSignature(documentId, signature); } 看起来逻辑清晰,没什么问题。但上线后,用户反馈:某些文档的数字签名校验失败。 排查后发现:当用户打开文档验证时,文件内容和签名时不一致——明明签名后没人再编辑过,怎么文件变了? 根本原因:forcesave 是异步的 翻了 ONLYOFFICE 的文档,才发现 forcesave 的调用流程是这样的: 后端调用 forcesave API ↓ ONLYOFFICE Document Server 接收请求 ↓ Document Server 在内部调度保存任务(异步) ↓ 保存完成后,Document Server 回调后端的 Callback Handler ↓ 后端在回调中收到最新的文件 URL 也就是说,forcesave() 返回时,文件还没保存完成。真正的文件更新是在回调里发生的。 ...

November 15, 2025 · 后端开发 / 分布式 · 3 min · 631 words · map[email:onetick@live.cn name:Hongyu]

当 if-else 长成一棵树:用策略模式重构 OnlyOffice 回调处理

问题从哪里开始 项目里集成了 OnlyOffice 文档编辑器,功能挺好用,但回调处理这块慢慢变成了"噩梦"。 OnlyOffice 会推送各种回调,比如用户保存文档、强制保存、文档关闭等等。每种回调有不同的 status 字段,对应不同的处理逻辑。一开始代码写得很"朴素": // FileServiceImpl.java - 曾经的模样 public void onlyOfficeCallback(OnlyOfficeCallbackDTO callbackDTO, File file) { if (callbackDTO.getStatus() == 2) { if (callbackDTO.getActions() != null && callbackDTO.getActions().stream().anyMatch(a -> a.getType() == 0)) { // 保存逻辑:下载文档、更新文件... // 几十行代码 } } else if (callbackDTO.getStatus() == 6) { // 强制保存逻辑 // 又是几十行代码 } else if (callbackDTO.getStatus() == 1) { // 正在编辑... } else if (...) { // 更多分支... } } 然后还有 Command 调用——主动向 OnlyOffice 发命令的逻辑,也堆在同一个 Service 里: public void sendCommand(String command, Map<String, Object> params) { if ("forcesave".equals(command)) { // 强制保存命令逻辑 } else if ("info".equals(command)) { // 获取信息命令逻辑 } // 更多分支... } 问题来了: ...

November 13, 2025 · 后端开发 / 设计模式 · 3 min · 559 words · map[email:onetick@live.cn name:Hongyu]