西藏巴青项目

大屏免密登录技术方案.md 6.5KB

大屏 — 免密登录 — 技术方案

ruoyi-screen 等大屏前端自动登录:无需账号密码与验证码,通过 RSA 加密 UUID 换取若依 JWT,再访问各 bigScreen:* 看板接口。


1. 技术架构

说明
后端 RuoYi v3.9.2(springboot2):JDK 8、Spring MVC
代码包 com.ruoyi.web.modules.screenScreenLoginController / ScreenLoginService / ScreenLoginRsaSupport / ScreenLoginProperties
鉴权 登录接口 @Anonymous 免鉴权;登录成功后与普通若依接口一致,请求头 Authorization: Bearer <token>
专用账号 sys_user 预置用户(默认 screen_viewer),建议仅授予 bigScreen:*:query
加密 RSA/ECB/PKCS1Padding,与若依后台 jsencrypt 密钥格式兼容
客户端 IP 不校验白名单/黑名单;仅写入登录日志

流程

sequenceDiagram
    participant FE as ruoyi-screen
    participant API as baqing-admin
    FE->>API: GET /bigScreen/publicKey
    API-->>FE: data.publicKey
    FE->>FE: 生成 UUID,JSEncrypt 公钥加密
    FE->>API: POST /bigScreen/login(X-Screen-Token 或 body.token)
    API->>API: 私钥解密,校验 UUID 格式
    API-->>FE: token(JWT)
    FE->>API: GET /bigScreen/home/dashboard(Authorization)

2. 配置

2.1 application.yml

bigscreen:
  login:
    enabled: false          # 生产按需 true
    rsa-public-key: ""      # Base64 公钥(可含换行,服务端会去除空白)
    rsa-private-key: ""     # Base64 私钥(仅服务端,勿下发前端)
    username: screen_viewer # 专用 sys_user 登录名
说明
enabled false 时公钥接口与登录接口均返回「大屏免密登录未启用」
rsa-public-key / rsa-private-key 须成对;开发环境可与 ruoyi-ui/src/utils/jsencrypt.js 中示例密钥一致
username 不存在、已删除或停用时登录失败

密钥生成:可使用 在线 RSA 密钥对工具(JSEncrypt 格式);生产建议 2048 位独立密钥对。


3. 接口

Base Path/bigScreen(含 server.servlet.context-path、网关前缀须补齐)。

序号 说明 方法 路径 鉴权
3.1 获取 RSA 公钥 GET /bigScreen/publicKey 无(@Anonymous
3.2 免密登录换 Token POST /bigScreen/login 无(@Anonymous

3.1 获取 RSA 公钥

请求:无 Body。

成功响应AjaxResult):

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "publicKey": "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH..."
  }
}
字段 类型 说明
data.publicKey string Base64 RSA 公钥,供 JSEncrypt setPublicKey

失败:未启用或未配置密钥时 ServiceException,统一错误提示。

3.2 免密登录

认证载荷(二选一,优先请求头):

方式 说明
请求头 X-Screen-Token: <RSA 密文 Base64>
Body { "token": "<RSA 密文 Base64>" }

前端步骤

  1. 调用 §3.1 获取 publicKey
  2. 生成标准 UUID(如 crypto.randomUUID()
  3. 使用 JSEncrypt 以公钥加密 UUID 字符串(明文 36 字符)
  4. 将 JSEncrypt 返回的 Base64 密文作为 token 提交

成功响应(与 POST /login 一致):

{
  "code": 200,
  "msg": "操作成功",
  "token": "eyJhbGciOiJIUzI1NiJ9..."
}

后续看板请求:Authorization: Bearer <token>

失败场景

场景 提示(示例)
未启用 大屏免密登录未启用
未配置密钥 大屏免密登录未配置 RSA 密钥
密文为空 / 解密失败 / 明文非 UUID 大屏登录认证失败
专用账号不存在 大屏专用账号不存在
账号删除 / 停用 若依标准 user.password.delete / user.blocked

4. 实现要点

职责
ScreenLoginController 路由、X-Screen-Token / Body 取值
ScreenLoginService 启用与密钥校验、解密验 UUID、加载专用用户、签发 JWT
ScreenLoginRsaSupport RSA 加解密、UUID.fromString 格式校验
ScreenLoginProperties 绑定 bigscreen.login.*
ScreenLoginConfig @EnableConfigurationProperties

UUID 校验:解密明文经 UUID.fromString 解析,须为标准 8-4-4-4-12 十六进制格式(大小写均可)。

安全说明

  • 每次登录应生成新 UUID 再加密,避免重放固定密文(服务端当前仅校验格式,不存 nonce)。
  • 私钥仅存服务端配置,禁止写入前端或版本库(生产用环境变量/密钥管理)。
  • 大屏看板接口仍依赖 JWT + bigScreen:*:query 权限,与免密登录入口分离。

5. 前端示例(JSEncrypt)

import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'

async function screenAutoLogin(apiBase) {
  const keyRes = await fetch(`${apiBase}/bigScreen/publicKey`).then(r => r.json())
  const uuid = crypto.randomUUID()
  const encryptor = new JSEncrypt()
  encryptor.setPublicKey(keyRes.data.publicKey)
  const cipher = encryptor.encrypt(uuid)
  if (!cipher) throw new Error('RSA encrypt failed')

  const loginRes = await fetch(`${apiBase}/bigScreen/login`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token: cipher })
  }).then(r => r.json())

  return loginRes.token
}

6. 交付清单

  • ScreenLoginControllerGET /bigScreen/publicKeyPOST /bigScreen/login
  • ScreenLoginService + ScreenLoginRsaSupport + ScreenLoginProperties
  • application.ymlbigscreen.login.*
  • 单元测试:ScreenLoginRsaSupportTestScreenLoginServiceTestScreenLoginControllerApiTest
  • ruoyi-screen 对接自动登录(按本方案调用公钥 + 登录接口)

7. 与各看板模块关系

模块 看板 Base Path 登录后权限示例
首页 /bigScreen/home bigScreen:home:query
交易销售 /bigScreen/tradeSales bigScreen:tradeSales:query
疫病风险 /bigScreen/epidemicRisk bigScreen:epidemicRisk:query
畜牧资源 /bigScreen/livestockResource bigScreen:livestockResource:query
共同富裕 /bigScreen/commonProsperity bigScreen:commonProsperity:query

免密登录不替代上述权限校验;专用账号须在若依中配置对应菜单权限。