259 lines
7.5 KiB
Markdown
259 lines
7.5 KiB
Markdown
|
|
# Frontend Password Transfer Encryption Implementation Plan
|
|||
|
|
|
|||
|
|
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|||
|
|
|
|||
|
|
**Goal:** 为正式密码提交接口补上前端加密发送能力,让登录、注册、个人修改密码、管理员重置密码、管理员新增用户在请求发出前只对密码字段做 AES 加密。
|
|||
|
|
|
|||
|
|
**Architecture:** 在 `ruoyi-ui` 新增统一的密码传输加密工具和字段映射辅助方法,由 API 层在提交请求前克隆并加密受控字段。页面组件继续持有明文表单值,现有表单校验和交互文案保持不变。
|
|||
|
|
|
|||
|
|
**Tech Stack:** Vue 2、Axios、`crypto-js`、Node 脚本测试、Vue CLI 4
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Task 1: 搭建前端加密工具与测试基线
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `ruoyi-ui/package.json`
|
|||
|
|
- Modify: `ruoyi-ui/package-lock.json`
|
|||
|
|
- Create: `ruoyi-ui/src/utils/passwordTransfer.js`
|
|||
|
|
- Create: `ruoyi-ui/tests/password-transfer-api.test.js`
|
|||
|
|
|
|||
|
|
- [ ] **Step 1: 写前端失败测试脚本**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const encrypted = encryptPasswordFields(
|
|||
|
|
{ password: 'admin123', code: '8888' },
|
|||
|
|
['password'],
|
|||
|
|
'1234567890abcdef'
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
assert.notStrictEqual(encrypted.password, 'admin123')
|
|||
|
|
assert.strictEqual(encrypted.code, '8888')
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const requestConfig = login('admin', 'admin123', '8888', 'uuid-1')
|
|||
|
|
assert.strictEqual(requestConfig.data.password !== 'admin123', true)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: 运行测试确认当前失败**
|
|||
|
|
|
|||
|
|
Run: `cd ruoyi-ui && node tests/password-transfer-api.test.js`
|
|||
|
|
Expected: FAIL,工具文件或 API 加密行为尚不存在
|
|||
|
|
|
|||
|
|
- [ ] **Step 3: 新增依赖、脚本和最小工具实现**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import CryptoJS from 'crypto-js'
|
|||
|
|
|
|||
|
|
export function encryptPasswordFields(payload, fields, key) {
|
|||
|
|
const next = { ...payload }
|
|||
|
|
fields.forEach((field) => {
|
|||
|
|
if (next[field]) {
|
|||
|
|
next[field] = CryptoJS.AES.encrypt(next[field], CryptoJS.enc.Utf8.parse(key), {
|
|||
|
|
mode: CryptoJS.mode.ECB,
|
|||
|
|
padding: CryptoJS.pad.Pkcs7
|
|||
|
|
}).toString()
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
return next
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
"scripts": {
|
|||
|
|
"test:password-transfer": "node tests/password-transfer-api.test.js"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 4: 重新运行前端测试**
|
|||
|
|
|
|||
|
|
Run: `cd ruoyi-ui && npm run test:password-transfer`
|
|||
|
|
Expected: PASS
|
|||
|
|
|
|||
|
|
- [ ] **Step 5: 提交本任务**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add ruoyi-ui/package.json ruoyi-ui/package-lock.json ruoyi-ui/src/utils/passwordTransfer.js ruoyi-ui/tests/password-transfer-api.test.js
|
|||
|
|
git commit -m "新增前端密码加密工具"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Task 2: 接入登录与注册接口加密
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `ruoyi-ui/src/api/login.js`
|
|||
|
|
|
|||
|
|
- [ ] **Step 1: 扩展测试覆盖登录与注册 API**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const loginConfig = login('admin', 'admin123', '8888', 'uuid-1')
|
|||
|
|
assert.notStrictEqual(loginConfig.data.password, 'admin123')
|
|||
|
|
assert.strictEqual(loginConfig.data.username, 'admin')
|
|||
|
|
|
|||
|
|
const registerConfig = register({ username: 'u1', password: 'p1', confirmPassword: 'p1', code: '8888' })
|
|||
|
|
assert.notStrictEqual(registerConfig.data.password, 'p1')
|
|||
|
|
assert.strictEqual(registerConfig.data.confirmPassword, 'p1')
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: 运行测试确认失败**
|
|||
|
|
|
|||
|
|
Run: `cd ruoyi-ui && npm run test:password-transfer`
|
|||
|
|
Expected: FAIL,`login.js` 尚未对正式接口密码字段加密
|
|||
|
|
|
|||
|
|
- [ ] **Step 3: 在 API 层接入加密工具**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const data = encryptPasswordFields({ username, password, code, uuid }, ['password'], process.env.VUE_APP_PASSWORD_TRANSFER_KEY)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const payload = encryptPasswordFields(data, ['password'], process.env.VUE_APP_PASSWORD_TRANSFER_KEY)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
要求:
|
|||
|
|
- 只加密 `password`
|
|||
|
|
- 保持字段名不变
|
|||
|
|
- 不在页面组件中写加密逻辑
|
|||
|
|
|
|||
|
|
- [ ] **Step 4: 重新运行前端测试**
|
|||
|
|
|
|||
|
|
Run: `cd ruoyi-ui && npm run test:password-transfer`
|
|||
|
|
Expected: PASS
|
|||
|
|
|
|||
|
|
- [ ] **Step 5: 提交本任务**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add ruoyi-ui/src/api/login.js ruoyi-ui/tests/password-transfer-api.test.js
|
|||
|
|
git commit -m "接入登录注册密码加密"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Task 3: 接入个人修改密码接口加密
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `ruoyi-ui/src/api/system/user.js`
|
|||
|
|
|
|||
|
|
- [ ] **Step 1: 扩展测试覆盖 `updateUserPwd`**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const config = updateUserPwd('oldPwd', 'newPwd')
|
|||
|
|
assert.notStrictEqual(config.data.oldPassword, 'oldPwd')
|
|||
|
|
assert.notStrictEqual(config.data.newPassword, 'newPwd')
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: 运行测试确认失败**
|
|||
|
|
|
|||
|
|
Run: `cd ruoyi-ui && npm run test:password-transfer`
|
|||
|
|
Expected: FAIL,`updateUserPwd` 仍发送明文
|
|||
|
|
|
|||
|
|
- [ ] **Step 3: 只在 API 层加密两个密码字段**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const data = encryptPasswordFields(
|
|||
|
|
{ oldPassword, newPassword },
|
|||
|
|
['oldPassword', 'newPassword'],
|
|||
|
|
process.env.VUE_APP_PASSWORD_TRANSFER_KEY
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
要求:
|
|||
|
|
- 页面 `resetPwd.vue` 不改
|
|||
|
|
- 继续让前端表单在明文状态下完成确认密码校验
|
|||
|
|
|
|||
|
|
- [ ] **Step 4: 重新运行测试**
|
|||
|
|
|
|||
|
|
Run: `cd ruoyi-ui && npm run test:password-transfer`
|
|||
|
|
Expected: PASS
|
|||
|
|
|
|||
|
|
- [ ] **Step 5: 提交本任务**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add ruoyi-ui/src/api/system/user.js ruoyi-ui/tests/password-transfer-api.test.js
|
|||
|
|
git commit -m "接入个人修改密码加密"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Task 4: 接入管理员新增用户与重置密码接口加密
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `ruoyi-ui/src/api/system/user.js`
|
|||
|
|
- Modify: `ruoyi-ui/.env.development`
|
|||
|
|
- Modify: `ruoyi-ui/.env.staging`
|
|||
|
|
- Modify: `ruoyi-ui/.env.production`
|
|||
|
|
|
|||
|
|
- [ ] **Step 1: 扩展测试覆盖 `addUser` 与 `resetUserPwd`**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const addConfig = addUser({ userName: 'u1', password: 'initPwd', nickName: 'n1' })
|
|||
|
|
assert.notStrictEqual(addConfig.data.password, 'initPwd')
|
|||
|
|
|
|||
|
|
const resetConfig = resetUserPwd(2, 'resetPwd')
|
|||
|
|
assert.notStrictEqual(resetConfig.data.password, 'resetPwd')
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: 运行测试确认失败**
|
|||
|
|
|
|||
|
|
Run: `cd ruoyi-ui && npm run test:password-transfer`
|
|||
|
|
Expected: FAIL,`addUser`、`resetUserPwd` 仍发送明文
|
|||
|
|
|
|||
|
|
- [ ] **Step 3: 在受控接口接入加密并补环境配置**
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const payload = encryptPasswordFields(data, ['password'], process.env.VUE_APP_PASSWORD_TRANSFER_KEY)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```dotenv
|
|||
|
|
VUE_APP_PASSWORD_TRANSFER_KEY=请替换为16位固定密钥
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
要求:
|
|||
|
|
- 只改 `addUser`、`resetUserPwd`
|
|||
|
|
- `updateUser` 不做密码加密处理
|
|||
|
|
- 三套环境文件都补同名配置项
|
|||
|
|
|
|||
|
|
- [ ] **Step 4: 重新运行测试**
|
|||
|
|
|
|||
|
|
Run: `cd ruoyi-ui && npm run test:password-transfer`
|
|||
|
|
Expected: PASS
|
|||
|
|
|
|||
|
|
- [ ] **Step 5: 提交本任务**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add ruoyi-ui/src/api/system/user.js ruoyi-ui/.env.development ruoyi-ui/.env.staging ruoyi-ui/.env.production ruoyi-ui/tests/password-transfer-api.test.js
|
|||
|
|
git commit -m "接入用户密码接口前端加密"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Task 5: 汇总验证与前端实施记录
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Create: `doc/implementation-report-2026-03-30-login-password-encryption-frontend.md`
|
|||
|
|
|
|||
|
|
- [ ] **Step 1: 运行前端目标测试**
|
|||
|
|
|
|||
|
|
Run: `cd ruoyi-ui && npm run test:password-transfer`
|
|||
|
|
Expected: PASS,受控 API 的密码字段都按预期加密
|
|||
|
|
|
|||
|
|
- [ ] **Step 2: 运行一次前端构建验证**
|
|||
|
|
|
|||
|
|
Run: `cd ruoyi-ui && npm run build:stage`
|
|||
|
|
Expected: PASS,新增依赖、环境变量与 API 修改不影响构建
|
|||
|
|
|
|||
|
|
- [ ] **Step 3: 写前端实施记录**
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
# 密码加密传输前端实施记录
|
|||
|
|
- 新增强制密码字段加密工具
|
|||
|
|
- 登录、注册、修改密码、重置密码、新增用户在 API 层加密
|
|||
|
|
- 页面表单逻辑保持不变
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- [ ] **Step 4: 再次检查 git 状态**
|
|||
|
|
|
|||
|
|
Run: `git status --short`
|
|||
|
|
Expected: 仅包含前端实现文件与 `doc/implementation-report-2026-03-30-login-password-encryption-frontend.md`
|
|||
|
|
|
|||
|
|
- [ ] **Step 5: 提交本任务**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add doc/implementation-report-2026-03-30-login-password-encryption-frontend.md
|
|||
|
|
git commit -m "完成密码加密传输前端实现"
|
|||
|
|
```
|