feat(utils): 增加本地存储加密及控制

This commit is contained in:
chen.home 2023-01-14 01:14:22 +08:00
parent bba1b16e1a
commit 65db1d063e
8 changed files with 90 additions and 18 deletions

1
.env
View File

@ -11,3 +11,4 @@ VITE_HASH_ROUTE = Y
VITE_AUTH_ROUTE_MODE=dynamic VITE_AUTH_ROUTE_MODE=dynamic
# 存储前缀 # 存储前缀
VITE_STORAGE_PREFIX = "" VITE_STORAGE_PREFIX = ""
VITE_STORAGE_ENCRYPT_SECRET = '__CryptoJS_Secret__'

View File

@ -1 +1,3 @@
VITE_HTTP_PROXY=N VITE_HTTP_PROXY=N
# 开启localStorage内容加密
VITE_STORAGE_ENCRYPT=N

View File

@ -6,3 +6,6 @@ VITE_COMPRESS_TYPE=gzip
# 是否开启打包依赖分析 # 是否开启打包依赖分析
VITE_VISUALIZER=N VITE_VISUALIZER=N
# 开启localStorage内容加密
VITE_STORAGE_ENCRYPT=Y

View File

@ -31,11 +31,13 @@
"./src/**/*.{vue,js,jsx,ts,tsx,json}": "eslint --fix" "./src/**/*.{vue,js,jsx,ts,tsx,json}": "eslint --fix"
}, },
"dependencies": { "dependencies": {
"@types/crypto-js": "^4.1.1",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",
"@vueuse/core": "^9.10.0", "@vueuse/core": "^9.10.0",
"@wangeditor/editor": "^5.1.23", "@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12", "@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.2.2", "axios": "^1.2.2",
"crypto-js": "^4.1.1",
"echarts": "^5.4.1", "echarts": "^5.4.1",
"md-editor-v3": "^2.7.2", "md-editor-v3": "^2.7.2",
"pinia": "^2.0.28", "pinia": "^2.0.28",

11
src/typings/env.d.ts vendored
View File

@ -31,17 +31,18 @@ interface ImportMetaEnv {
/** 是否开启打包压缩 */ /** 是否开启打包压缩 */
readonly VITE_COMPRESS_OPEN?: 'Y' | 'N'; readonly VITE_COMPRESS_OPEN?: 'Y' | 'N';
/** 压缩算法类型 */ /** 压缩算法类型 */
readonly VITE_COMPRESS_TYPE?: readonly VITE_COMPRESS_TYPE?: 'gzip' | 'brotliCompress' | 'deflate' | 'deflateRaw';
| 'gzip'
| 'brotliCompress'
| 'deflate'
| 'deflateRaw';
/** hash路由模式 */ /** hash路由模式 */
readonly VITE_HASH_ROUTE?: 'Y' | 'N'; readonly VITE_HASH_ROUTE?: 'Y' | 'N';
/** 路由加载模式 */ /** 路由加载模式 */
readonly VITE_AUTH_ROUTE_MODE?: 'static' | 'dynamic'; readonly VITE_AUTH_ROUTE_MODE?: 'static' | 'dynamic';
/** 本地存储前缀 */ /** 本地存储前缀 */
readonly VITE_STORAGE_PREFIX?: string; readonly VITE_STORAGE_PREFIX?: string;
/** 本地存储内容开启加密 */
readonly VITE_STORAGE_ENCRYPT?: 'Y' | 'N';
/** 本地存储加密密钥 */
readonly VITE_STORAGE_ENCRYPT_SECRET: string;
/** 后端服务的环境类型 */ /** 后端服务的环境类型 */
readonly VITE_SERVICE_ENV?: ServiceEnvType; readonly VITE_SERVICE_ENV?: ServiceEnvType;
} }

41
src/utils/crypto.ts Normal file
View File

@ -0,0 +1,41 @@
import CryptoJS from 'crypto-js';
import { isObject } from './is';
const { VITE_STORAGE_ENCRYPT, VITE_STORAGE_ENCRYPT_SECRET } = import.meta.env;
/**
*
* @param data -
*/
export function encrypto(data: any) {
let newData = data;
if (isObject(data)) {
newData = JSON.stringify(data);
}
if (VITE_STORAGE_ENCRYPT === 'N') {
return newData;
}
return CryptoJS.AES.encrypt(newData, VITE_STORAGE_ENCRYPT_SECRET).toString();
}
/**
*
* @param cipherText -
*/
export function decrypto(cipherText: string) {
if (VITE_STORAGE_ENCRYPT === 'N') {
return JSON.parse(cipherText);
}
const bytes = CryptoJS.AES.decrypt(cipherText, VITE_STORAGE_ENCRYPT_SECRET);
const originalText = bytes.toString(CryptoJS.enc.Utf8);
if (originalText) {
return JSON.parse(originalText);
}
return null;
}

View File

@ -1,3 +1,4 @@
import { encrypto, decrypto } from './crypto';
// 读取缓存前缀 // 读取缓存前缀
const prefix = import.meta.env.VITE_STORAGE_PREFIX as string; const prefix = import.meta.env.VITE_STORAGE_PREFIX as string;
@ -17,7 +18,7 @@ function createLocalStorage() {
value, value,
expire: new Date().getTime() + expire * 1000, expire: new Date().getTime() + expire * 1000,
}; };
const json = JSON.stringify(storageData); const json = encrypto(storageData);
window.localStorage.setItem(prefix + key, json); window.localStorage.setItem(prefix + key, json);
} }
@ -26,7 +27,11 @@ function createLocalStorage() {
if (!json) return null; if (!json) return null;
let storageData: StorageData | null = null; let storageData: StorageData | null = null;
storageData = JSON.parse(json as string); try {
storageData = decrypto(json);
} catch {
// 防止解析失败
}
if (storageData) { if (storageData) {
const { value, expire } = storageData; const { value, expire } = storageData;
@ -34,7 +39,7 @@ function createLocalStorage() {
return value; return value;
} }
} }
local.remove(key); remove(key);
return null; return null;
} }
@ -58,20 +63,24 @@ function createLocalStorage() {
function createSessionStorage() { function createSessionStorage() {
function set(key: string, value: any) { function set(key: string, value: any) {
const json = JSON.stringify(value); const json = encrypto(value);
window.sessionStorage.setItem(prefix + key, json); window.sessionStorage.setItem(prefix + key, json);
} }
function get<T>(key: string) { function get<T>(key: string) {
const json = sessionStorage.getItem(prefix + key); const json = sessionStorage.getItem(prefix + key);
let data: T | null = null; if (!json) return null;
if (json) {
try { let storageData;
data = JSON.parse(json); try {
} catch { storageData = decrypto(json);
// 防止解析失败 } catch {
} // 防止解析失败
} }
return data;
if (storageData) {
return storageData;
}
return null;
} }
function remove(key: string) { function remove(key: string) {
window.sessionStorage.removeItem(prefix + key); window.sessionStorage.removeItem(prefix + key);
@ -79,6 +88,13 @@ function createSessionStorage() {
function clear() { function clear() {
window.sessionStorage.clear(); window.sessionStorage.clear();
} }
return {
set,
get,
remove,
clear,
};
} }
export const local = createLocalStorage(); export const local = createLocalStorage();

View File

@ -35,6 +35,7 @@
<n-form-item path="account"> <n-form-item path="account">
<n-input <n-input
v-model:value="formValue.account" v-model:value="formValue.account"
clearable
placeholder="输入账号" placeholder="输入账号"
> >
<template #prefix> <template #prefix>
@ -47,6 +48,7 @@
v-model:value="formValue.pwd" v-model:value="formValue.pwd"
type="password" type="password"
placeholder="输入密码" placeholder="输入密码"
clearable
show-password-on="click" show-password-on="click"
> >
<template #prefix> <template #prefix>
@ -64,7 +66,9 @@
<n-space align="center"> <n-space align="center">
<n-input <n-input
v-model:value="formValue.code" v-model:value="formValue.code"
clearable
placeholder="输入验证码" placeholder="输入验证码"
:maxlength="4"
> >
<template #prefix> <template #prefix>
<i-icon-park-outline-message /> <i-icon-park-outline-message />
@ -155,6 +159,8 @@ function handleLogin() {
if (isRemember.value) { if (isRemember.value) {
local.set('login_account', { account, pwd }); local.set('login_account', { account, pwd });
} else {
local.remove('login_account');
} }
authStore.login(account, pwd); authStore.login(account, pwd);