供
ruoyi-screen等大屏前端自动登录:无需账号密码与验证码,通过 RSA 加密 UUID 换取若依 JWT,再访问各bigScreen:*看板接口。
| 项 | 说明 |
|---|---|
| 后端 | RuoYi v3.9.2(springboot2):JDK 8、Spring MVC |
| 代码包 | com.ruoyi.web.modules.screen(ScreenLoginController / 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)
application.ymlbigscreen:
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 位独立密钥对。
Base Path:/bigScreen(含 server.servlet.context-path、网关前缀须补齐)。
| 序号 | 说明 | 方法 | 路径 | 鉴权 |
|---|---|---|---|---|
| 3.1 | 获取 RSA 公钥 | GET | /bigScreen/publicKey |
无(@Anonymous) |
| 3.2 | 免密登录换 Token | POST | /bigScreen/login |
无(@Anonymous) |
请求:无 Body。
成功响应(AjaxResult):
{
"code": 200,
"msg": "操作成功",
"data": {
"publicKey": "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH..."
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
data.publicKey |
string | Base64 RSA 公钥,供 JSEncrypt setPublicKey |
失败:未启用或未配置密钥时 ServiceException,统一错误提示。
认证载荷(二选一,优先请求头):
| 方式 | 说明 |
|---|---|
| 请求头 | X-Screen-Token: <RSA 密文 Base64> |
| Body | { "token": "<RSA 密文 Base64>" } |
前端步骤:
publicKeycrypto.randomUUID())token 提交成功响应(与 POST /login 一致):
{
"code": 200,
"msg": "操作成功",
"token": "eyJhbGciOiJIUzI1NiJ9..."
}
后续看板请求:Authorization: Bearer <token>。
失败场景
| 场景 | 提示(示例) |
|---|---|
| 未启用 | 大屏免密登录未启用 |
| 未配置密钥 | 大屏免密登录未配置 RSA 密钥 |
| 密文为空 / 解密失败 / 明文非 UUID | 大屏登录认证失败 |
| 专用账号不存在 | 大屏专用账号不存在 |
| 账号删除 / 停用 | 若依标准 user.password.delete / user.blocked |
| 类 | 职责 |
|---|---|
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 十六进制格式(大小写均可)。
安全说明:
bigScreen:*:query 权限,与免密登录入口分离。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
}
ScreenLoginController:GET /bigScreen/publicKey、POST /bigScreen/loginScreenLoginService + ScreenLoginRsaSupport + ScreenLoginPropertiesapplication.yml → bigscreen.login.*ScreenLoginRsaSupportTest、ScreenLoginServiceTest、ScreenLoginControllerApiTestruoyi-screen 对接自动登录(按本方案调用公钥 + 登录接口)| 模块 | 看板 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 |
免密登录不替代上述权限校验;专用账号须在若依中配置对应菜单权限。