让网页安全地拿到 Nacos 里指定的 JSON 配置

真实录屏:在 Nacos 发布配置后,页面无需刷新即更新
真实录屏:Nacos 控制台一点发布,页面跟着更新(同源 SSE)。点击可放大。

为什么需要它

页面上的公告、功能开关、活动文案经常存在 Nacos 里。

运营一点发布,就希望线上页面跟着变,而不是等下一次前端发版。

但网页不该自己去连 Nacos。

所以还是让你的 Spring Boot 去连 Nacos,网页只连自己的后端。你在配置里写清楚哪些名字可以给网页看,后端校验后再推过去。

场景自己写 / 直连nacos-web-config
账号写到哪写进前端谁都能看到;拿到账号还能改、删凭据只留在后端
能放开多少Nacos 按命名空间授权,没法只放开一条只放出你点名的那些名字
对 Nacos 的暴露面直接对外易被刷挂,依赖它的后端都会受影响网页只连你的后端
运营推了坏内容规则自己定,页面容易直接挂丢掉坏数据,继续用上一份好的
发布后要尽快出现在页面继续轮询,或自己做推送后端直接推变更
Nacos 临时挂了自己约定怎么表现不把页面上的值清掉
接入成本缓存、协议、测试都自己扛依赖 + 一段 YAML + subscribe()

数据怎么走

不另起进程、不另开库、不另做控制台。装进直接对浏览器服务的 Spring Boot 应用即可。图可点击节点、缩放查看;完整交互页可单独打开。

打开完整架构图

nacos-web-config:
  enabled: true          # 默认关闭,须显式启用
  access: public        # 必填:public | authenticated
  nacos:
    server-addr: 127.0.0.1:8848
  exposures:              # 白名单:逻辑名 → 固定 Nacos 坐标
    ui:
      group: WEB_DEMO
      data-id: web-demo.public.json
      max-bytes: 65536
  • YAML
  • 白名单

授权写在 YAML 里

对外暴露哪些配置,由白名单决定:逻辑名映射固定 Nacos 坐标,并带字节上限。登录与鉴权沿用宿主现有安全链,Starter 不自建登录。

快速开始

后端加依赖并声明白名单,前端订阅。完整配置项见 GitHub README「配置参考」。

  1. Step 1

    后端引入 Starter 并声明白名单

    <dependency>
      <groupId>io.github.fatmii.nacoswebconfig</groupId>
      <artifactId>nacos-web-config-spring-boot-starter</artifactId>
      <version>0.1.0</version>
    </dependency>
    nacos-web-config:
      enabled: true
      access: public
      nacos:
        server-addr: 127.0.0.1:8848
      exposures:
        ui:
          group: WEB_DEMO
          data-id: web-demo.public.json
          max-bytes: 65536

    启动后暴露 SSE 端点 /_web-config/v1/stream(可用 path 修改)。access 选 public(能访问端点即可读白名单)或 authenticated(请求上已有登录身份才接流)。

  2. Step 2

    前端订阅配置

    $ npm install @fatmii/nacos-web-config
    import { createWebConfig } from '@fatmii/nacos-web-config'
    
    // endpoint 可省略(默认 /_web-config/v1/stream);decode 可省略
    const config = createWebConfig({
      definitions: {
        ui: { fallback: { announcement: '' } },
      },
    })
    
    const unsubscribe = config.subscribe('ui', state => {
      renderAnnouncement(state.value?.announcement ?? '')
    })
    // config.get('ui') 只读当前状态;首次 subscribe() 才建立共享连接
  3. Step 3

    本地演示

    # 需要 JDK 17、Maven,以及能跑 linux/amd64 的 Docker
    $ cd dev-environment
    $ docker compose --project-name nacos-web-config-local up -d nacos2
    # 等 http://127.0.0.1:18848/nacos 可打开
    
    $ cd ..\java
    $ $env:NACOS_SERVER_ADDR='127.0.0.1:18848'
    $ mvn -pl examples/spring-mvc -am spring-boot:run

    打开 http://127.0.0.1:8080/,在 Nacos 的 WEB_DEMO 组发布 web-demo.public.json(例如 {"announcement":"hello"})。页面应在数秒内更新。更细说明见仓库 java/examples/spring-mvc/ 与 dev-environment/。

兼容性

依赖版本说明
Java17+Spring Boot 3.x,Servlet/MVC
Nacos Client2.5.3唯一支持的客户端线
Nacos Server2.5.3含浏览器完整链路实测(Java 测试 + browser E2E)
Nacos Server3.2.3适配层测过;完整浏览器链路暂不声称支持
浏览器现代浏览器需 fetch + ReadableStream,无 EventSource 回退

常见问题

Nacos 会不会暴露给前端?

不会。浏览器只与你的后端同源自带的 SSE 端点通信,且只能访问 YAML 白名单中显式声明的逻辑名;Nacos 地址、鉴权凭据、group / dataId / namespace 都不经过浏览器。

为什么不让浏览器直连 Nacos?

账号写进前端谁都能看到,而且 Nacos 账号还能改配置。Nacos 也不能只放开「这一条」给网页看。直接对外还容易把配置中心打挂。所以应由你的后端去连 Nacos;网页只连你的后端,并且只能拿到你事先允许的那些配置。

为什么用 SSE,不用轮询或 WebSocket?

这是单向配置推送。SSE 走普通 HTTP:同源、复用现有鉴权与网关、浏览器成本低。协议自带单调序号与流 ID,快照先于增量,乱序拒收,重连再取快照。轮询给不了这些语义;WebSocket 则要自己实现。

后端随便开个接口给前端轮询,不就行了?

自己写轮询接口,鉴权、白名单映射、坏数据容错、推送与断线恢复都得自己扛。本项目把这些做成可复用能力:只放出你点名的配置、坏数据不弄挂页面、发布后直接推到页面,接入成本是依赖 + YAML + subscribe()。

鉴权怎么做?

access 只有 public 与 authenticated,必须显式声明,否则启动失败。public:能访问端点即可读白名单(只读)。authenticated:请求上已有登录身份才接流;Starter 只看 getUserPrincipal(),不关心身份怎么挂上,也不自己登录。没有登录机制时一律 401。级别按整条流,不能逐键设。

运营推了坏配置会怎样?

内容有硬校验:必须是 JSON 对象且不超过 max-bytes,不合格的内容被拒绝且不会覆盖最近有效值。Nacos 整体不可达时也只是标记 stale,页面继续用最后一次有效配置渲染。

有哪些限制?
  • Nacos 3.2.3:适配层测过了;完整浏览器链路还没在 3.2.3 上声称支持。
  • 只有 Servlet MVC,没有 WebFlux。
  • 值必须是不超过 max-bytes 的 JSON 对象。
  • SDK 只发 ESM;老浏览器要自己做打包/兼容。
  • 没有管理界面;配置仍在 Nacos 控制台改。
有没有全部配置项的清单?

有。README 的「配置参考」给了一份带默认值的完整 YAML,每项旁边用注释说明作用。原则只有一条:填错就启动失败并给精确报错,不会悄悄用默认值跑起来。

要暴露多条配置,就要开多条连接吗?

不用。一个后端实例的整张白名单共用一条连接:浏览器订阅时把所有键拼在同一个请求上(单连接默认上限 32 键),首个快照一次带回全部键,之后哪条变了就单独推哪条。一个实例只连一个 namespace;要跨 namespace 就再加一个实例。

新增一条要暴露的配置,要重新打包部署吗?

不用改业务代码:在 application.yml 里加一条允许对外的配置,重启即可。前端再在 definitions 里补同名项。经常改的字段可以放在同一个 JSON 里,运营改内容就能立刻生效,不必老是加新的对外项。

前端必须用某个框架吗?

不绑定框架。SDK 是 TypeScript 库,subscribe / get 纯订阅模型,React、Vue 或原生页面均可直接使用;需要支持 fetch + ReadableStream 的现代浏览器。

更多说明见 GitHub README

活跃维护
v0.1.0

首个公开发布

Spring Boot Starter + 浏览器 SDK 已上 Maven Central / npm。

网页只拿白名单里的 JSON;

运营在 Nacos 一发布,同源 SSE 推到页面。

获取

0.1.0 已在 Maven Central 与 npm。加依赖或 npm install 即可。

npm 已发布

npm install @fatmii/nacos-web-config,0.1.0,TypeScript ESM、零运行时依赖。

查看包页

源码构建

准备 JDK 17+、Maven、Node.js。后端在 java/ 执行 mvn verify;前端在 browser/ 执行 npm ci && npm test && npm run build。

查看构建方法

也可从 GitHub 源码 自行构建。安全漏洞请勿开公开 Issue,报告方式见 SECURITY.md。