chore(other): 登录仅加密密码字段(豁免整体加密)
Some checks failed
Build and Deploy (admin.xpcool.com) / build-and-deploy (push) Failing after 1h0m22s

- loginApi 恒走密码字段混合加密,提交 {username, encryptedKey, encryptedData}
- 请求拦截器豁免 /auth/login 整体加密
This commit is contained in:
夏犀麟 2026-08-28 00:29:00 +08:00
parent f8463e9f84
commit f70f5dcff8
3 changed files with 11 additions and 14 deletions

View File

@ -1,6 +1,8 @@
# admin.xpcool.com 变更记录
> 倒序最新在上。格式YYYY-MM-DD | 类型 | 摘要
2026-08-27 | CHG | 登录接口豁免全量加密永远只加密密码字段loginApi 始终走 hybridEncryptLogin提交 {username 明文, encryptedKey, encryptedData}request.ts PLAIN_ROUTE_FRAGMENTS 增 /auth/login请求拦截器不再整体加密登录 body。全量模式 5 项 + dev 15 项 E2E 验证通过
2026-08-27 | CHG | 全量请求/响应加密(生产 VITE_GLOB_API_ENCRYPT=true①crypto.ts 增 encryptPayload整体加密任意对象返回 aesKeyB64 会话密钥)+ decryptPayloadAES-GCM 解密后端响应,密文=nonce||ciphertext||tag②request.ts 增 installCryptoInterceptors——请求拦截器将整个 JSON body 混合加密public-key 豁免、FormData/无 body 跳过、响应解密拦截器最先注册axios 响应拦截器按注册顺序执行)还原 {code,message,data}requestClient 与 baseRequestClient 均安装apiFullBodyEncrypt/fetchPublicKeyForCrypto 导出③auth.ts loginApi、system.ts createAdmin/resetAdminPassword 全量模式下直接传明文密码由拦截器整体加密(开发模式仍走密码字段混合加密);④.env.production VITE_GLOB_API_ENCRYPT=true / .env.development=false。⚠TS 坑Uint8Array.subarray 返回 ArrayBufferLike 泛型不满足 BufferSource需 new Uint8Array() 拷贝axios 类型从 @vben/request re-export 导入web-tdesign 未声明 axios 依赖。typecheck+oxlint 全绿,全量/仅密码两种模式 E2E 均通过
2026-08-27 | CHG | 登录/创建/重置密码全链路加密传输RSA+AES 混合加密,与后端配套):①新增 src/utils/crypto.ts——Web Crypto API 零依赖importKey('spki') 导入后端公钥、随机 AES-256-GCM 加密载荷nonce 12B 前置、GCM tag 随密文、RSA-OAEP(SHA-256) 加密 AES 密钥,输出 {encryptedKey, encryptedData};公钥 5 分钟内存缓存。②api/core/auth.tsgetPublicKeyApi并发去重+ loginApi 先拉公钥再加密 username/password 提交网络传输无明文密码。③api/system.tscreateAdmin/resetAdminPassword 的 password 走 hybridEncryptField 加密encryptField 复用公钥缓存。④注意Web Crypto 仅安全上下文可用https/localhost/127.0.0.1http://IP 访问会明确报错。typecheck + oxlint 全绿

View File

@ -1,5 +1,4 @@
import {
apiFullBodyEncrypt,
baseRequestClient,
fetchPublicKeyForCrypto,
requestClient,
@ -30,18 +29,12 @@ export async function getPublicKeyApi(): Promise<string> {
}
/**
* +
* - {username,password} body
* - AES {username,password,ts}RSA AES
* {encryptedKey, encryptedData}
* +
* AES {username,password,ts}
* RSA AES {username, encryptedKey, encryptedData}
* 便
*/
export async function loginApi(data: AuthApi.LoginParams) {
if (apiFullBodyEncrypt) {
return requestClient.post<AuthApi.LoginResult>(
'/api/service/admin/system/auth/login',
{ username: data.username, password: data.password },
);
}
const publicKey = await getPublicKeyApi();
const { encryptedKey, encryptedData } = await hybridEncryptLogin(
publicKey,
@ -50,7 +43,7 @@ export async function loginApi(data: AuthApi.LoginParams) {
);
return requestClient.post<AuthApi.LoginResult>(
'/api/service/admin/system/auth/login',
{ encryptedKey, encryptedData },
{ username: data.username, encryptedKey, encryptedData },
);
}

View File

@ -37,8 +37,10 @@ const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
export const apiFullBodyEncrypt =
import.meta.env.VITE_GLOB_API_ENCRYPT === 'true';
/** 全量加密豁免端点path 片段匹配),此类请求明文收发 */
const PLAIN_ROUTE_FRAGMENTS = ['/public-key'];
/** path
* - public-key
* - username + */
const PLAIN_ROUTE_FRAGMENTS = ['/public-key', '/auth/login'];
// 公钥拉取并发去重:同一时刻只发一次请求。
let publicKeyPromise: null | Promise<string> = null;