feat(projects): 登录记住密码加密保存

This commit is contained in:
xlsea
2025-12-08 14:38:55 +08:00
parent f7d8d1898e
commit 90c52d979e
7 changed files with 77 additions and 58 deletions
+3
View File
@@ -13,6 +13,9 @@ VITE_APP_WEBSOCKET=N
# app client id
VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
# 记住密码 AES 加密密钥
VITE_REMEMBER_ME_AES_KEY=pC4aO6cD2uU7hA0bK6iD4vE1mV8sU8xG
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
VITE_APP_ENCRYPT=Y
# AES 加密头标识
+3
View File
@@ -10,6 +10,9 @@ VITE_APP_WEBSOCKET=N
# app client id
VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
# 记住密码 AES 加密密钥
VITE_REMEMBER_ME_AES_KEY=pC4aO6cD2uU7hA0bK6iD4vE1mV8sU8xG
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
VITE_APP_ENCRYPT=Y
# AES 加密头标识
+3
View File
@@ -10,6 +10,9 @@ VITE_APP_WEBSOCKET=N
# app client id
VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
# 记住密码 AES 加密密钥
VITE_REMEMBER_ME_AES_KEY=pC4aO6cD2uU7hA0bK6iD4vE1mV8sU8xG
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
VITE_APP_ENCRYPT=Y
# AES 加密头标识
+54 -54
View File
@@ -972,73 +972,73 @@ packages:
'@mermaid-js/parser@0.6.3':
resolution: {integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==}
'@napi-rs/canvas-android-arm64@0.1.83':
resolution: {integrity: sha512-TbKM2fh9zXjqFIU8bgMfzG7rkrIYdLKMafgPhFoPwKrpWk1glGbWP7LEu8Y/WrMDqTGFdRqUmuX89yQEzZbkiw==}
'@napi-rs/canvas-android-arm64@0.1.84':
resolution: {integrity: sha512-pdvuqvj3qtwVryqgpAGornJLV6Ezpk39V6wT4JCnRVGy8I3Tk1au8qOalFGrx/r0Ig87hWslysPpHBxVpBMIww==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [android]
'@napi-rs/canvas-darwin-arm64@0.1.83':
resolution: {integrity: sha512-gp8IDVUloPUmkepHly4xRUOfUJSFNvA4jR7ZRF5nk3YcGzegSFGeICiT4PnYyPgSKEhYAFe1Y2XNy0Mp6Tu8mQ==}
'@napi-rs/canvas-darwin-arm64@0.1.84':
resolution: {integrity: sha512-A8IND3Hnv0R6abc6qCcCaOCujTLMmGxtucMTZ5vbQUrEN/scxi378MyTLtyWg+MRr6bwQJ6v/orqMS9datIcww==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
'@napi-rs/canvas-darwin-x64@0.1.83':
resolution: {integrity: sha512-r4ZJxiP9OgUbdGZhPDEXD3hQ0aIPcVaywtcTXvamYxTU/SWKAbKVhFNTtpRe1J30oQ25gWyxTkUKSBgUkNzdnw==}
'@napi-rs/canvas-darwin-x64@0.1.84':
resolution: {integrity: sha512-AUW45lJhYWwnA74LaNeqhvqYKK/2hNnBBBl03KRdqeCD4tKneUSrxUqIv8d22CBweOvrAASyKN3W87WO2zEr/A==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.83':
resolution: {integrity: sha512-Uc6aSB05qH1r+9GUDxIE6F5ZF7L0nTFyyzq8ublWUZhw8fEGK8iy931ff1ByGFT04+xHJad1kBcL4R1ZEV8z7Q==}
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.84':
resolution: {integrity: sha512-8zs5ZqOrdgs4FioTxSBrkl/wHZB56bJNBqaIsfPL4ZkEQCinOkrFF7xIcXiHiKp93J3wUtbIzeVrhTIaWwqk+A==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
'@napi-rs/canvas-linux-arm64-gnu@0.1.83':
resolution: {integrity: sha512-eEeaJA7V5KOFq7W0GtoRVbd3ak8UZpK+XLkCgUiFGtlunNw+ZZW9Cr/92MXflGe7o3SqqMUg+f975LPxO/vsOQ==}
'@napi-rs/canvas-linux-arm64-gnu@0.1.84':
resolution: {integrity: sha512-i204vtowOglJUpbAFWU5mqsJgH0lVpNk/Ml4mQtB4Lndd86oF+Otr6Mr5KQnZHqYGhlSIKiU2SYnUbhO28zGQA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@napi-rs/canvas-linux-arm64-musl@0.1.83':
resolution: {integrity: sha512-cAvonp5XpbatVGegF9lMQNchs3z5RH6EtamRVnQvtoRtwbzOMcdzwuLBqDBQxQF79MFbuZNkWj3YRJjZCjHVzw==}
'@napi-rs/canvas-linux-arm64-musl@0.1.84':
resolution: {integrity: sha512-VyZq0EEw+OILnWk7G3ZgLLPaz1ERaPP++jLjeyLMbFOF+Tr4zHzWKiKDsEV/cT7btLPZbVoR3VX+T9/QubnURQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@napi-rs/canvas-linux-riscv64-gnu@0.1.83':
resolution: {integrity: sha512-WFUPQ9qZy31vmLxIJ3MfmHw+R2g/mLCgk8zmh7maJW8snV3vLPA7pZfIS65Dc61EVDp1vaBskwQ2RqPPzwkaew==}
'@napi-rs/canvas-linux-riscv64-gnu@0.1.84':
resolution: {integrity: sha512-PSMTh8DiThvLRsbtc/a065I/ceZk17EXAATv9uNvHgkgo7wdEfTh2C3aveNkBMGByVO3tvnvD5v/YFtZL07cIg==}
engines: {node: '>= 10'}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@napi-rs/canvas-linux-x64-gnu@0.1.83':
resolution: {integrity: sha512-X9YwIjsuy50WwOyYeNhEHjKHO8rrfH9M4U8vNqLuGmqsZdKua/GrUhdQGdjq7lTgdY3g4+Ta5jF8MzAa7UAs/g==}
'@napi-rs/canvas-linux-x64-gnu@0.1.84':
resolution: {integrity: sha512-N1GY3noO1oqgEo3rYQIwY44kfM11vA0lDbN0orTOHfCSUZTUyiYCY0nZ197QMahZBm1aR/vYgsWpV74MMMDuNA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@napi-rs/canvas-linux-x64-musl@0.1.83':
resolution: {integrity: sha512-Vv2pLWQS8EnlSM1bstJ7vVhKA+mL4+my4sKUIn/bgIxB5O90dqiDhQjUDLP+5xn9ZMestRWDt3tdQEkGAmzq/A==}
'@napi-rs/canvas-linux-x64-musl@0.1.84':
resolution: {integrity: sha512-vUZmua6ADqTWyHyei81aXIt9wp0yjeNwTH0KdhdeoBb6azHmFR8uKTukZMXfLCC3bnsW0t4lW7K78KNMknmtjg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [musl]
'@napi-rs/canvas-win32-x64-msvc@0.1.83':
resolution: {integrity: sha512-K1TtjbScfRNYhq8dengLLufXGbtEtWdUXPV505uLFPovyGHzDUGXLFP/zUJzj6xWXwgUjHNLgEPIt7mye0zr6Q==}
'@napi-rs/canvas-win32-x64-msvc@0.1.84':
resolution: {integrity: sha512-YSs8ncurc1xzegUMNnQUTYrdrAuaXdPMOa+iYYyAxydOtg0ppV386hyYMsy00Yip1NlTgLCseRG4sHSnjQx6og==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
'@napi-rs/canvas@0.1.83':
resolution: {integrity: sha512-f9GVB9VNc9vn/nroc9epXRNkVpvNPZh69+qzLJIm9DfruxFqX0/jsXG46OGWAJgkO4mN0HvFHjRROMXKVmPszg==}
'@napi-rs/canvas@0.1.84':
resolution: {integrity: sha512-88FTNFs4uuiFKP0tUrPsEXhpe9dg7za9ILZJE08pGdUveMIDeana1zwfVkqRHJDPJFAmGY3dXmJ99dzsy57YnA==}
engines: {node: '>= 10'}
'@napi-rs/wasm-runtime@0.2.12':
@@ -2343,8 +2343,8 @@ packages:
resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==}
engines: {node: '>=0.10.0'}
baseline-browser-mapping@2.9.3:
resolution: {integrity: sha512-8QdH6czo+G7uBsNo0GiUfouPN1lRzKdJTGnKXwe12gkFbnnOUaUKGN55dMkfy+mnxmvjwl9zcI4VncczcVXDhA==}
baseline-browser-mapping@2.9.4:
resolution: {integrity: sha512-ZCQ9GEWl73BVm8bu5Fts8nt7MHdbt5vY9bP6WGnUh+r3l8M7CgfyTlwsgCbMC66BNxPr6Xoce3j66Ms5YUQTNA==}
hasBin: true
big.js@5.2.2:
@@ -3820,8 +3820,8 @@ packages:
jsonfile@6.2.0:
resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==}
katex@0.16.25:
resolution: {integrity: sha512-woHRUZ/iF23GBP1dkDQMh1QBad9dmr8/PAwNA54VrSOVYgI12MAcE14TqnDdQOdzyEonGzMepYnqBMYdsoAr8Q==}
katex@0.16.27:
resolution: {integrity: sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==}
hasBin: true
keyv@4.5.4:
@@ -6005,48 +6005,48 @@ snapshots:
dependencies:
langium: 3.3.1
'@napi-rs/canvas-android-arm64@0.1.83':
'@napi-rs/canvas-android-arm64@0.1.84':
optional: true
'@napi-rs/canvas-darwin-arm64@0.1.83':
'@napi-rs/canvas-darwin-arm64@0.1.84':
optional: true
'@napi-rs/canvas-darwin-x64@0.1.83':
'@napi-rs/canvas-darwin-x64@0.1.84':
optional: true
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.83':
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.84':
optional: true
'@napi-rs/canvas-linux-arm64-gnu@0.1.83':
'@napi-rs/canvas-linux-arm64-gnu@0.1.84':
optional: true
'@napi-rs/canvas-linux-arm64-musl@0.1.83':
'@napi-rs/canvas-linux-arm64-musl@0.1.84':
optional: true
'@napi-rs/canvas-linux-riscv64-gnu@0.1.83':
'@napi-rs/canvas-linux-riscv64-gnu@0.1.84':
optional: true
'@napi-rs/canvas-linux-x64-gnu@0.1.83':
'@napi-rs/canvas-linux-x64-gnu@0.1.84':
optional: true
'@napi-rs/canvas-linux-x64-musl@0.1.83':
'@napi-rs/canvas-linux-x64-musl@0.1.84':
optional: true
'@napi-rs/canvas-win32-x64-msvc@0.1.83':
'@napi-rs/canvas-win32-x64-msvc@0.1.84':
optional: true
'@napi-rs/canvas@0.1.83':
'@napi-rs/canvas@0.1.84':
optionalDependencies:
'@napi-rs/canvas-android-arm64': 0.1.83
'@napi-rs/canvas-darwin-arm64': 0.1.83
'@napi-rs/canvas-darwin-x64': 0.1.83
'@napi-rs/canvas-linux-arm-gnueabihf': 0.1.83
'@napi-rs/canvas-linux-arm64-gnu': 0.1.83
'@napi-rs/canvas-linux-arm64-musl': 0.1.83
'@napi-rs/canvas-linux-riscv64-gnu': 0.1.83
'@napi-rs/canvas-linux-x64-gnu': 0.1.83
'@napi-rs/canvas-linux-x64-musl': 0.1.83
'@napi-rs/canvas-win32-x64-msvc': 0.1.83
'@napi-rs/canvas-android-arm64': 0.1.84
'@napi-rs/canvas-darwin-arm64': 0.1.84
'@napi-rs/canvas-darwin-x64': 0.1.84
'@napi-rs/canvas-linux-arm-gnueabihf': 0.1.84
'@napi-rs/canvas-linux-arm64-gnu': 0.1.84
'@napi-rs/canvas-linux-arm64-musl': 0.1.84
'@napi-rs/canvas-linux-riscv64-gnu': 0.1.84
'@napi-rs/canvas-linux-x64-gnu': 0.1.84
'@napi-rs/canvas-linux-x64-musl': 0.1.84
'@napi-rs/canvas-win32-x64-msvc': 0.1.84
optional: true
'@napi-rs/wasm-runtime@0.2.12':
@@ -6938,7 +6938,7 @@ snapshots:
highlight.js: 11.11.1
hotkeys-js: 3.13.15
jsbarcode: 3.12.1
katex: 0.16.25
katex: 0.16.27
lowlight: 3.3.0
mermaid: 11.12.2
nzh: 1.0.14
@@ -7018,7 +7018,7 @@ snapshots:
highlight.js: 11.11.1
hotkeys-js: 3.13.15
jsbarcode: 3.12.1
katex: 0.16.25
katex: 0.16.27
lowlight: 3.3.0
mermaid: 11.12.2
nzh: 1.0.14
@@ -7584,7 +7584,7 @@ snapshots:
mixin-deep: 1.3.2
pascalcase: 0.1.1
baseline-browser-mapping@2.9.3: {}
baseline-browser-mapping@2.9.4: {}
big.js@5.2.2: {}
@@ -7626,7 +7626,7 @@ snapshots:
browserslist@4.28.1:
dependencies:
baseline-browser-mapping: 2.9.3
baseline-browser-mapping: 2.9.4
caniuse-lite: 1.0.30001759
electron-to-chromium: 1.5.266
node-releases: 2.0.27
@@ -9231,7 +9231,7 @@ snapshots:
optionalDependencies:
graceful-fs: 4.2.11
katex@0.16.25:
katex@0.16.27:
dependencies:
commander: 8.3.0
@@ -9395,7 +9395,7 @@ snapshots:
dagre-d3-es: 7.0.13
dayjs: 1.11.19
dompurify: 3.3.0
katex: 0.16.25
katex: 0.16.27
khroma: 2.1.0
lodash-es: 4.17.21
marked: 16.4.2
@@ -9692,7 +9692,7 @@ snapshots:
pdfjs-dist@5.4.296:
optionalDependencies:
'@napi-rs/canvas': 0.1.83
'@napi-rs/canvas': 0.1.84
perfect-debounce@1.0.0: {}
+1 -1
View File
@@ -45,7 +45,7 @@ declare namespace StorageType {
/** The last login user id */
lastLoginUserId: CommonType.IdType;
/** The login form rember */
loginRember: Api.Auth.PwdLoginForm;
loginRember: string;
/** The tenant id */
tenantId: CommonType.IdType;
}
+1
View File
@@ -113,6 +113,7 @@ declare namespace Env {
/** The launch editor */
readonly VITE_DEVTOOLS_LAUNCH_EDITOR?: import('vite-plugin-vue-devtools').VitePluginVueDevToolsOptions['launchEditor'];
readonly VITE_APP_CLIENT_ID?: string;
readonly VITE_REMEMBER_ME_AES_KEY?: string;
readonly VITE_APP_ENCRYPT?: CommonType.YesOrNo;
readonly VITE_HEADER_FLAG?: string;
readonly VITE_APP_RSA_PUBLIC_KEY?: string;
+12 -3
View File
@@ -2,13 +2,18 @@
import { computed, reactive, ref } from 'vue';
import type { SelectOption } from 'naive-ui';
import { useLoading } from '@sa/hooks';
import CryptoJS from 'crypto-js';
import { fetchCaptchaCode, fetchTenantList } from '@/service/api';
import { fetchSocialAuthBinding } from '@/service/api/system';
import { useAuthStore } from '@/store/modules/auth';
import { useRouterPush } from '@/hooks/common/router';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { localStg } from '@/utils/storage';
import { decryptWithAes, encryptWithAes } from '@/utils/crypto';
import { $t } from '@/locales';
const aesKey = CryptoJS.enc.Utf8.parse(import.meta.env.VITE_REMEMBER_ME_AES_KEY || 'pC4aO6cD2uU7hA0bK6iD4vE1mV8sU8xG');
defineOptions({
name: 'PwdLogin'
});
@@ -33,6 +38,7 @@ const model: Api.Auth.PwdLoginForm = reactive({
username: 'admin',
password: 'admin123'
});
type RuleKey = Extract<keyof Api.Auth.PwdLoginForm, 'username' | 'password' | 'code' | 'tenantId'>;
const rules = computed<Record<RuleKey, App.Global.FormRule[]>>(() => {
@@ -48,6 +54,7 @@ const rules = computed<Record<RuleKey, App.Global.FormRule[]>>(() => {
return loginRules;
});
async function handleFetchTenantList() {
startTenantLoading();
const { data, error } = await fetchTenantList();
@@ -71,7 +78,7 @@ async function handleSubmit() {
// 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码
if (remberMe.value) {
const { tenantId, username, password } = model;
localStg.set('loginRember', { tenantId, username, password });
localStg.set('loginRember', encryptWithAes(JSON.stringify({ tenantId, username, password }), aesKey));
} else {
// 否则移除
localStg.remove('loginRember');
@@ -101,8 +108,10 @@ handleFetchCaptchaCode();
function handleLoginRember() {
const loginRember = localStg.get('loginRember');
if (!loginRember) return;
remberMe.value = true;
Object.assign(model, loginRember);
try {
remberMe.value = true;
Object.assign(model, JSON.parse(decryptWithAes(loginRember, aesKey)));
} catch {}
}
handleLoginRember();