新闻详情

新闻详情

首页 / 资讯中心 / 详情

DzzOffice 集成 OnlyOffice:JWT令牌报错与密钥对齐

发布时间:2026/10/1 18:59:05来源:尧图网络
DzzOffice 集成 OnlyOffice:JWT令牌报错与密钥对齐
装过 DzzOffice 又挂了 OnlyOffice 的人大概率都见过这一行红字文档安全令牌未正确形成。它通常出现在编辑器 iframe 的正文区域底下还跟一句请联系文档服务器管理员。第一次遇到的人往往会往网络、往端口、往跨域上想折腾半天防火墙和白名单结果跟这些一点关系都没有。这个报错的本质非常单纯——OnlyOffice Document Server 在打开文档时要对浏览器传来的配置做一次 JWT 验签签不出来、或者签的名字对不上它就直接把编辑器毙掉只留这一句话给你。DzzOffice 这边负责生成编辑器配置并把它塞进页面OnlyOffice 那边负责验。两边的密钥只要有一个字节不一样或者 DzzOffice 这个版本压根就没往配置里塞令牌红字就必然出现。所以所谓临时解决办法其实就两条路要么把 Document Server 的校验关掉要么把两边的密钥对齐。前者快、粗暴、五分钟能见效后者体面、安全、但要求你搞清版本和配置层级。我下面会把这套东西从报错出自谁一路讲到改完还报错怎么办最后再说说什么情况下这两招都该退休。1. 这行红字是 OnlyOffice 在报不是 DzzOffice 在报很多人第一反应是去 DzzOffice 的应用日志里翻翻半天翻不到因为这条错误根本没走到 DzzOffice 的后端逻辑。搞清楚谁在说话能省下至少一半的排查时间。1.1 一次打开文档背后其实跑了两段链路你在 DzzOffice 里点开一个 docx发生的事情大致是这样DzzOffice 后端拼出一份 JSON 配置包含文档地址、回调地址、权限、编辑器尺寸等等把这份 JSON 渲染进页面浏览器加载 OnlyOffice 的 api.js拿着这份配置去请求 Document ServerDocument Server 拿到配置后先做一次校验确认这份配置是可信来源发来的然后才去把文档文件拉过来、渲染成编辑器。关键就在确认可信来源这一步。OnlyOffice 用的手段是 JWTDzzOffice 用约定的密钥把整份配置当成 payload 签一个 HS256 的令牌塞在配置对象里一起发过去Document Server 用同样的密钥重新算一遍签名对得上才放行。对不上、或者压根没令牌它返回的就是那句文档安全令牌未正确形成。所以这行字是 Document Server 吐出来的DzzOffice 只是个传话的看客你去 DzzOffice 日志里找是找不到的。1.2 JWT 校验开关在 OnlyOffice 里分了三个位置不少人以为令牌校验就是一个总开关实际上 OnlyOffice 把它拆成了三块分别管不同方向的请求。这是我踩过坑才记住的配置位置管的是什么关掉后的影响token.enable.browser浏览器侧提交的编辑器配置关掉后打开文档不再要求令牌即你遇到的这个报错token.enable.request.inboxDocument Server 往回调地址发请求时带令牌关掉后你的回调接口不再收到 Authorization 头token.enable.request.outbox部分内部转发请求的令牌一般集成场景下影响较小如果你只是想让文档能打开改的是第一项。很多人改了request.inbox发现没用就是位置找错了。而真正容易被忽略的是后两项——一旦你把浏览器侧校验关了回调侧还开着文档能打开、能编辑但保存时静默失败你会看到文档已保存的提示刷新之后内容还是旧的。这种问题比打不开更折磨人因为它的异常表现是看起来正常。所以动手之前先想清楚你只是要临时打开看看还是准备长期用。临时打开三块一起关长期用老老实实对齐密钥。2. 五分钟自查先确认是令牌没带还是带了但签错同一个报错根因可能完全不同。前者是 DzzOffice 没塞令牌后者是两边密钥不一致。这两件事的处理方式相反——前者你得关校验或者升级插件后者你只要把密钥抄对就行。所以别急着改配置先确认是哪一种。2.1 进 Document Server 看真实的开关状态OnlyOffice 的配置是分层的default.json是出厂默认local.json是本地覆盖运行时以合并后的结果为准。你直接看default.json会看到一大堆字段但那不一定是生效值。最靠谱的方式是先扫一眼默认结构确认你这个版本里字段名叫什么grep -n -A 25 token /etc/onlyoffice/documentserver/default.json | head -60这一步的意义在于不同大版本的字段命名有差异。早期版本就是inbox、outbox、session三段密钥新一点的版本里你能看到和browser相关的键。你要照着你自己机器上吐出来的结构去写local.json而不是照抄网上某篇三年前的文章。抄错层级的后果是配置文件语法没错、服务也能起来但那个开关根本没生效你会以为改了没用其实是没改到点上。然后再看本地覆盖层cat /etc/onlyoffice/documentserver/local.json如果这个文件里没有token这一段说明你在用出厂默认。而很多新版本安装完之后默认就是开启校验并且自动生成了一串随机密钥——这时候你只要拿到那串密钥填到 DzzOffice 里就行根本不用关任何东西。密钥在哪还是在local.json里services.CoAuthoring.token.secret下面那几个string。注意如果你是用容器起 Document Serverlocal.json在容器内部路径是/etc/onlyoffice/documentserver/local.json宿主机上直接cat是看不到的。2.2 抓一次配置请求看 token 字段到底存不存在打开 DzzOffice 里的文档页面按 F12 打开开发者工具切到 Network过滤CommandService或者直接过滤docservice刷新页面。你会看到一条发往 Document Server 的 POST 请求请求体就是那份编辑器配置。在请求体里搜token。三种结果对应三种病完全没有 token 字段说明 DzzOffice 这个插件版本不支持 JWT或者你没在插件设置里填密钥。这种情况你只能去 Document Server 侧关校验没有别的临时办法。有 token但形如一个很短的普通字符串那不是合法 JWT。合法 JWT 一定是三段、用点分隔、第一段以eyJ开头。有 token是标准三段结构那大概率是密钥不一致或者密钥里有隐形字符。顺便看一眼这个请求返回的内容。如果返回体里带error和-4之类的错误码基本就坐实了是令牌问题不用再往别处想。2.3 用一段 Python 验签把猜变成确定密钥不一致这件事靠肉眼比对是不靠谱的尤其是密钥里有容易混淆的字符时。最省事的办法是把抓到的 token 拿去本地验一遍import base64, json, hmac, hashlib token 把这里换成你抓到的 token secret b把这里换成你 local.json 里的密钥 head, payload, sig token.split(.) def b64d(s): return base64.urlsafe_b64decode(s * (-len(s) % 4)) print(json.loads(b64d(head))) print(json.loads(b64d(payload))) want base64.urlsafe_b64encode( hmac.new(secret, f{head}.{payload}.encode(), hashlib.sha256).digest() ).rstrip(b).decode() print(签名是否匹配:, want sig)跑出来如果是False密钥不一致实锤。同时打印出来的 payload 里你能看到iat和exp两个时间戳顺手核对一下——如果exp比当前时间早很多说明不是密钥问题是服务器时钟跑偏了那是另一个坑第 5 节会讲。如果 payload 能解出来但结构很怪比如里面塞的不是配置对象而是一个url字符串那说明 DzzOffice 用的是旧版签名格式和你这个版本的 Document Server 对不上。这种情况关校验是最快的路。3. 止血方案一Document Server 侧关掉令牌校验这条路就是把门锁拆了。五分钟能搞定代价是任何能访问到你 Document Server 的人都可以构造一份配置去拉文档。内网自用、临时验证、演示环境问题不大放到公网别这么干。3.1 改 local.json 的最小改动集原则是只动local.json永远别动default.json。后者会在升级时被覆盖而且体量巨大改错一格你都很难发现。一个最小可用的覆盖内容长这样{ services: { CoAuthoring: { token: { enable: { browser: false, request: { inbox: false, outbox: false } }, secret: { inbox: { string: 换成同一串密钥 }, outbox: { string: 换成同一串密钥 }, session: { string: 换成同一串密钥 } } } } } }这里有个细节值得说清楚我明明把校验关了为什么还留着secret段因为在你将来切回对齐密钥这条路的时候密钥得有一份明确的、你能看到的来源。如果它一直是安装时随机生成的那串你换个环境就再也找不回来了。所以我的习惯是第一次配置的时候就把密钥固定成自己指定的一串后面所有环境都统一用它。改之前先备份cp /etc/onlyoffice/documentserver/local.json /etc/onlyoffice/documentserver/local.json.bak改完用python3 -m json.tool过一遍确认语法没问题。JSON 一个多余逗号就能让服务起不来而且报错信息藏在日志里很容易漏。3.2 重启姿势不对等于没改改完文件不重启一切照旧这是最常见的改了没用。但重启的方式要看你的部署形态原生安装apt/rpm 装的那种一般由 supervisor 托管最稳的一刀是sudo supervisorctl restart all只重启 nginx 是没用的配置是 docservice 进程读的。容器部署docker exec -it 容器名 supervisorctl restart all或者直接docker restart 容器名。前者快后者更彻底。重启之后别急着开文档先看日志确认配置被读进去了tail -f /var/log/onlyoffice/documentserver/docservice/out.log回到 DzzOffice 刷新页面如果这次能进编辑器说明生效了。日志里如果还有令牌相关的告警那说明你的改动没落到实际生效的层级上回去核对default.json里的字段结构。3.3 容器部署的隐藏陷阱环境变量会把你的改动覆盖回去这个坑我踩得很结实值得单独拎出来说。如果你是用docker run或者 docker-compose 起的 Document Server很多镜像版本在容器启动时会根据环境变量重写local.json。也就是说你docker exec进去改好了文件supervisorctl restart all一切正常。然后某天你docker restart了一下容器配置全回来了报错也回来了你会一脸茫然地以为是谁动了你的机器。根源在启动脚本镜像里有JWT_ENABLED、JWT_SECRET、JWT_HEADER这几个环境变量启动时会把它们写进配置文件。所以正确做法是从一开始就在 compose 或 run 命令里定好例如environment: - JWT_ENABLEDfalse - JWT_SECRET你固定的那串密钥改完docker compose up -d重建容器而不是进去手动改文件。同理想长期用对齐密钥的方案就把JWT_ENABLEDtrue和JWT_SECRET一起定死两边抄同一串。还有一点少数版本会缓存一份合并后的配置重启后需要额外跑一次清理脚本才彻底生效。包里如果带了documentserver-flush-cache之类的命令可以顺手执行一次没有的话docker restart一般也够。4. 止血方案二两边密钥对齐比关校验体面如果 DzzOffice 的插件版本支持 JWT也就是设置界面里有密钥输入框那这条路才是正解。它不牺牲安全性也不会在升级后突然失效。麻烦点在于密钥这东西的对齐比想象中脆弱。4.1 DzzOffice 里密钥填在哪填什么进 DzzOffice 后台应用管理里找到 OnlyOffice 那个应用点它的设置。一般会有两个关键字段文档服务器地址和密钥。地址填到 Document Server 的根路径不要带/web-apps之类的后缀密钥填你local.json里secret那几段的string值。填完保存回到文档页面刷新。这里有个很反直觉的现象有些版本的插件改完设置后需要清一次缓存才生效因为在应用设置保存后前端拿到的还是旧配置。稳妥的做法是保存后退出登录再重新登录或者干脆清一下浏览器缓存。如果插件的设置里压根没有密钥这一栏那说明这个版本不支持 JWT。这种情况下别硬找直接把 Document Server 侧校验关掉更省事硬凑只会浪费时间。4.2 密钥里的隐形字符空格、引号、换行密钥不一致的案例里我遇到过的真实原因按出现频率排下来是这样的复制时带上了首尾空格。local.json里的值是string: abc123你从终端里cat出来复制的时候很容易把: 之后的那一点空白也带进去。密钥用了带引号的形式。有人图省事把密钥写成\abc123\多出来的转义引号会被算进签名。末尾换行。从文件里复制粘贴很容易带上一个不可见的换行符前端输入框里看不出来但参与签名时就是一个字节的差异。大小写被输入法改写。这个不常见但真发生过尤其是密钥里有l、I、O、0这类字符的时候。规避方法很简单密钥只用纯字母和数字长度控制在 32 位左右别放特殊符号别放中文。既好复制又不容易出错。生成方式随便openssl rand -hex 16出来的 32 位十六进制串就挺好用。填进去之后用第 2 节的验签脚本再验一次确认True了再往下走。这一步花两分钟能省掉后面半小时的反复。4.3 反向代理下密钥没变但校验失败的几种情况密钥明明一样还是报令牌错误那问题就转移到请求在中间被改了。如果你在 Document Server 前面挂了 nginx 做反代重点查这几件事请求体被截断或改写。有些代理配置会对 body 做缓冲或者重写配置 JSON 一旦被改动签名自然对不上。检查proxy_request_buffering和client_max_body_size相关设置。Header 被过滤。回调方向靠Authorization: Bearer xxx传令牌如果代理把这个头丢了回调就会失败。虽然它不直接导致你看到的那行红字但会造成能打开、不能保存。HTTPS 与 HTTP 混用。DzzOffice 走 https而配置里回调地址是 http浏览器会直接拦掉表现为编辑器加载不出来。反代上补X-Forwarded-Proto头通常能解决。这几条不一定会触发安全令牌未正确形成但它们和令牌问题是同一批人在同一个环境里高频遇到的一起排查能少走弯路。5. 改完还报错几个高频连带问题配置改对了、服务重启了、密钥也验过了刷新页面还是那行红字。这种时候别怀疑人生多半是缓存或者环境层面的问题。这一节列的几条都是我真实遇到过的。5.1 缓存三层浏览器、代理、应用设置Document Server 前端有一套自己的静态资源和接口缓存。改了配置之后浏览器里那份 api.js 和编辑器页面可能还是旧的。最直接的办法是强制刷新CtrlF5 或者无痕窗口打开先排除浏览器这一层。第二层是 Document Server 前面的 nginx。它对部分接口是有缓存的重启服务能清掉如果是独立的反代可能需要nginx -s reload。第三层是 DzzOffice 应用自身的配置缓存。有些插件会把文档服务器地址和密钥缓存到本地文件或数据库里后台保存了但运行态没更新。这种情况通常退出重新登录或清理站点缓存就能解决。三层都过一遍很多改了没用的悬案就破了。5.2 时间不同步与多实例密钥不一致JWT 里带iat和exp签发时间和校验时间之间的偏差如果太大验签会失败。服务器时间跑偏这种情况在闲置很久的测试机上特别常见。一条命令确认date -u和标准时间对一下差得离谱就先同步时间再试。这个坑的迷惑性在于它的报错文案和有令牌错误时一模一样你根本想不到是时钟的问题。另一个场景是多实例部署。如果你的 Document Server 前面挂了负载均衡后端有两台以上而只有其中一台改了密钥那么请求打到哪台就决定了成功还是失败表现为时好时坏、刷新几次就能打开。这种随机成功的现象非常有辨识度看到它基本就能锁定是多实例配置不一致。解决办法是把密钥统一写进镜像或者配置中心而不是手动一台台改。5.3 HTTPS 混合内容与回调地址不通安全令牌未正确形成本身跟 HTTPS 无关但在排查过程中很容易被一个相关现象带偏编辑器加载出来了红字没了可文档内容区域一片空白或者一直转圈。这通常是 Document Server 拉不到文件——回调地址或文件地址填成了外网访问不通的地址。判断方法很直接直接在浏览器里打开配置里的url字段那个地址就是你那份文档文件的直链看能不能下载下来。如果浏览器能下、Document Server 下不了那问题在 Document Server 到 DzzOffice 这条网络链路上而不是令牌。顺手记一条经验DzzOffice 后台填的文档服务器地址必须是浏览器能访问到的地址而不是127.0.0.1或者容器内部 IP。有人填了内网 IP自己电脑在公司内网能打开一回家就全是问题。地址这块建议统一用域名。6. 什么时候必须把临时改成正式临时解决办法这五个字是有重量的。它意味着你现在做的事能解决问题但会留下一个需要还的账。什么时候必须还我给几个判断标准。6.1 关掉校验之后文档服务器等于不设防把token.enable.browser关掉之后Document Server 对任何人发来的编辑器配置都照单全收。这句话翻译成人话是只要能访问到你 Document Server 的地址别人就能构造一份配置让服务器去拉任意一个它能访问到的文件。注意这里的关键是它能访问到的也就是服务器所在网络里的资源包括内网的其他服务。内网隔离、只给自己用、当天用完就删的环境可以接受。一旦满足下面任意一条就该老老实实去对齐密钥Document Server 暴露在公网或者办公网有多个用户在共用你这个环境会长期存在服务器能访问到除文档目录之外的其他内部资源6.2 让配置在升级和重建后依然存活无论你选哪条路配置都得有抗升级和抗重建的能力。我给自己定的规矩是三条一是密钥固定化。第一次部署就指定一串自己生成的密钥写进部署脚本或者 compose 文件而不是用安装时随机生成的。随机密钥的问题是它只存在于那一台机器的那个文件里机器一重装你就再也找不回来了。二是配置来源单一。原生安装用local.json容器部署用环境变量二选一不要两处都改。两处都改的结果是某次重启之后你分不清生效的是哪个排错成本翻倍。三是升级后必查。OnlyOffice 大版本升级会调整配置结构字段位置可能变。升级完先按第 1 节的方法重新确认一遍字段名再看校验开关的状态别默认它还跟以前一样。6.3 一个我自己在用的排错顺序最后把我实际用的排查顺序写下来下次再遇到这行红字照着走一遍就行先看 Document Server 日志docservice/out.log确认报错确实来自令牌校验而不是别的错误被这行文案盖住了。抓一次打开文档的请求看配置里有没有token字段是不是合法三段 JWT。有 token 就验签True就往下查时间同步和缓存False就去核密钥。没 token 就看 DzzOffice 插件有没有密钥设置栏有就填、没有就关校验。关校验的话browser和request.inbox/outbox一起关别只关一半否则会出现能开不能存的怪毛病。重启对应进程容器部署记得先确认环境变量有没有把改动盖掉。这套流程走下来我遇到过的同类问题基本都能定位到具体一层很少有需要把整个环境推倒重来的情况。真正让我浪费时间的从来不是配置本身而是以为改了其实没生效和以为生效了其实改错了层这两件事。把这两件事按住剩下的都是体力活。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

无锡靠谱的微波炉变压器温控器/汽车加热垫温控器厂家质量参考评选 2026/10/1 19:49:24

无锡靠谱的微波炉变压器温控器/汽车加热垫温控器厂家质量参考评选

温控器选型核心原理入门:从功能逻辑到落地标准 微波炉变压器温控器、汽车加热垫温控器是工业与民用场景里的安全阀门,其核心作用是通过感知温度变化自动切断/接通电路,避免因过热引发短路、起火等安全事故。很多人对这类器件的认知仅停留在温…

阅读更多 →
北京汉臣健身器材 朝阳区门店 商用椭圆机与动感单车适配不同面积场馆 2026/10/1 19:49:24

北京汉臣健身器材 朝阳区门店 商用椭圆机与动感单车适配不同面积场馆

健身器材选购的行业科普:商用椭圆机与动感单车的本质区别商用椭圆机与动感单车虽然同属有氧器械,但在结构原理、适用人群、场地需求上存在显著差异。椭圆机通过滑轨与飞轮联动,实现脚步不离踏板的椭圆轨迹运动,对膝关节冲击小&…

阅读更多 →
机器人租赁的生死线:现场确认全流程风险与落地工具 2026/10/1 19:49:24

机器人租赁的生死线:现场确认全流程风险与落地工具

做机器人租赁这几年,我越来越觉得“现场确认”这四个字才是真正的生死线。合同签约只是把合作关系定下来,设备进场之后那一连串“开箱—部署—调试—演示—签字”的动作,才是决定这笔租赁到底是赚钱还是赔钱、客户是回头复购还是拉黑你的分水…

阅读更多 →
产品经理的本质:价值交换的设计师,从功能交付到可持续增长 2026/10/1 19:49:10

产品经理的本质:价值交换的设计师,从功能交付到可持续增长

说个产品经理都见过的场景:你花了三周画原型、磨交互、排期、盯开发,功能终于上线了。数据一看,核心按钮点击率不到3%,一周后更低了。这时候很多人会骂用户不懂产品,怪运营不给力,嫌投放量不够。但我做了几…

阅读更多 →
大厂Java面试:从Spring Boot到微服务架构的实战思维 2026/10/1 19:49:10

大厂Java面试:从Spring Boot到微服务架构的实战思维

1. “八股文”不是背答案:大厂Java面试的真正筛选逻辑先聊个很多人不愿意面对的事实:网上铺天盖地的“大厂Java面试题合集”“Java八股文背诵手册”,大家刷得都很努力,但真正能拿到Offer的人,往往不是背得最熟的那个。…

阅读更多 →
DeepTumorVQA2026——3D 腹部 CT 的分层式医学 VQA 基准之腹部器官全分割 2026/10/1 19:49:03

DeepTumorVQA2026——3D 腹部 CT 的分层式医学 VQA 基准之腹部器官全分割

今天将分享3D 腹部 CT 的分层式医学 VQA 基准之腹部器官全分割挑战赛实现版本,为了方便大家学习理解整个流程,将整个流程步骤进行了整理,并给出详细的步骤结果。感兴趣的朋友赶紧动手试一试吧。 一、DeepTumorVQA2026介绍 近年来医学视觉语…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉