You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mercure更换JWT密钥后Vue订阅端报401 Unauthorized问题求助

Mercure更换JWT密钥后前端订阅返回401排查方案

按以下优先级从高到低排查,90%的场景都是前两个问题导致的:

  • 确认JWT签名匹配问题
    Postman推送正常只能证明你用的发布端token和MERCURE_PUBLISHER_JWT_KEY匹配,和订阅端鉴权无关。换密钥后必须用新的MERCURE_SUBSCRIBER_JWT_KEY重新生成前端订阅用的JWT,之前用默认值!ChangeMe!签的旧token会直接验签失败。
    额外注意docker-compose的环境变量转义坑:如果新密钥带!、$、&这类yaml或者shell的特殊字符,没正确用引号包裹的话,容器里实际加载的密钥和你写在配置里的根本不是同一个。可以进容器执行命令校验实际生效的密钥:
    docker exec 你的mercure容器名 env | grep MERCURE_JWT_KEY
    
    如果输出值和你配置的不一致,给密钥加双引号包裹,或者换个不带特殊字符的密钥,也可以用docker secret传密钥规避转义问题。
  • 修正前端EventSource的错误写法
    浏览器原生EventSourceAPI根本不支持自定义请求头,你代码里写的headers配置项会被直接忽略,请求根本不会带mercureAuthorization这个头。
    之前默认密钥下能连上,是因为当时配置没触发强制订阅鉴权,走了匿名访问;换密钥后鉴权生效,请求没带有效token直接被拦了返回401。
    修复方法很简单,把订阅JWT作为access_token查询参数拼到URL里就行,修正后的代码:
    const url = new URL("https://localhost/.well-known/mercure");
    url.searchParams.append("topic", "chat");
    // 这里填你用新订阅密钥重新生成的有效JWT
    url.searchParams.append("access_token", "新生成的订阅JWT");
    const eventSource = new EventSource(url);
    eventSource.onmessage = (event) => {
      this.$notify({
        type: "success",
        text: "push",
      });
      console.log(event);
    };
    
    同域部署场景也可以用Cookie传鉴权凭证,只要在Mercure额外配置里把cors_origins、cookie_same_site配成和你前端域名匹配就行,这种方式不会把token暴露在URL里,安全性更高。
  • 校验JWT的权限声明
    如果前面两个问题都排除了还是401,检查你生成的订阅JWT的payload,必须包含对应topic的订阅权限,正确格式参考:
    {
      "mercure": {
        "subscribe": ["chat"]
      },
      "exp": 1735689600
    }
    
    哪怕签名是对的,没有配置对应topic的订阅权限,一样会返回401。

内容的提问来源于stack exchange,提问作者Vortex666

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 00:09:14