diff --git a/.env b/.env index 4894efd..d4c866d 100644 --- a/.env +++ b/.env @@ -16,9 +16,14 @@ VITE_API_URL = /api # ADMIN 服务地址 VITE_ADMIN_PROXY_PATH = http://scj-v3.zhxy.link/ -# 前端加密密钥 +# 前端加密密钥(AES,未启用 SM2 时使用) VITE_PWD_ENC_KEY='pigxpigxpigxpigx' +# 登录使用 SM2 加密密码:设为 true 时密码用 SM2 公钥加密,需后端配置 security.sm2-private-key +VITE_LOGIN_SM2_ENABLE=true +# SM2 公钥(十六进制,04 开头 130 字符),与后端私钥成对 +VITE_SM2_PUBLIC_KEY=04de67d5234bb13b5bbe524a71d1e48ac302014be3c3c6ba74b33bb5a125717b0e8873ad3971a6082138e0556a7ec334d460458c6c46753b65acc93ec1b99bb8fd + # OAUTH2 密码模式客户端信息 VITE_OAUTH2_PASSWORD_CLIENT='pig:pig' diff --git a/src/api/login/index.ts b/src/api/login/index.ts index f1df6f4..167f009 100644 --- a/src/api/login/index.ts +++ b/src/api/login/index.ts @@ -2,7 +2,7 @@ import request from '/@/utils/request'; import { Session } from '/@/utils/storage'; import { validateNull } from '/@/utils/validate'; import { useUserInfo } from '/@/stores/userInfo'; -import other from '/@/utils/other'; +import other, { sm2Encrypt } from '/@/utils/other'; /** * https://www.ietf.org/rfc/rfc6749.txt @@ -10,6 +10,11 @@ import other from '/@/utils/other'; */ const FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded'; +/** 登录是否使用 SM2 加密密码(需后端配置 SM2 私钥并支持 Enc-Flag: sm2) */ +const LOGIN_SM2_ENABLE = import.meta.env.VITE_LOGIN_SM2_ENABLE === 'true'; +/** SM2 公钥(十六进制,与后端私钥成对),用于前端加密密码 */ +const SM2_PUBLIC_KEY = import.meta.env.VITE_SM2_PUBLIC_KEY || ''; + // 登录方式 export enum LoginTypeEnum { PASSWORD, @@ -47,8 +52,15 @@ export enum SocialLoginEnum { export const login = (data: any) => { const basicAuth = 'Basic ' + window.btoa(import.meta.env.VITE_OAUTH2_PASSWORD_CLIENT); Session.set('basicAuth', basicAuth); - // 密码加密 - const encPassword = other.encryption(data.password, import.meta.env.VITE_PWD_ENC_KEY); + let encPassword: string; + let encFlag: string; + if (LOGIN_SM2_ENABLE && SM2_PUBLIC_KEY) { + encPassword = sm2Encrypt(data.password, SM2_PUBLIC_KEY); + encFlag = 'sm2'; + } else { + encPassword = other.encryption(data.password, import.meta.env.VITE_PWD_ENC_KEY); + encFlag = 'false'; + } const { username, randomStr, code, grant_type, scope } = data; return request({ url: '/auth/oauth2/token', @@ -59,7 +71,7 @@ export const login = (data: any) => { skipToken: true, Authorization: basicAuth, 'Content-Type': FORM_CONTENT_TYPE, - "Enc-Flag": "false", + 'Enc-Flag': encFlag, }, }); }; diff --git a/src/stores/userInfo.ts b/src/stores/userInfo.ts index 8ed17a0..fd43023 100644 --- a/src/stores/userInfo.ts +++ b/src/stores/userInfo.ts @@ -42,7 +42,6 @@ export const useUserInfo = defineStore('userInfo', { async login(data:any) { data.grant_type = 'password'; data.scope = 'server'; - return new Promise((resolve, reject) => { login(data) .then((res) => { diff --git a/src/utils/other.ts b/src/utils/other.ts index cc226c1..31e2b51 100644 --- a/src/utils/other.ts +++ b/src/utils/other.ts @@ -9,7 +9,7 @@ import {verifyUrl} from '/@/utils/toolsValidate'; import request from '/@/utils/request'; import {useMessage} from '/@/hooks/message'; import * as CryptoJS from 'crypto-js'; -import {sm4} from 'sm-crypto' +import { sm4, sm2 } from 'sm-crypto' import {validateNull} from './validate'; @@ -240,6 +240,17 @@ export function sm4Decryption(src: string, keyWord: string) { return sm4.decrypt(src, keyWord); } +/** + * SM2 加密(登录密码等,与后端 SM2 私钥解密配套) + * @param msg 明文 + * @param publicKey 后端提供的 SM2 公钥(十六进制,04 开头 130 字符或 128 字符压缩格式) + * @returns 十六进制密文,格式 C1C3C2 + */ +export function sm2Encrypt(msg: string, publicKey: string): string { + if (!msg || !publicKey) return msg; + return sm2.doEncrypt(msg, publicKey, 1); +} + /** * Base64 加密 * @param {*} src 明文 @@ -370,6 +381,9 @@ const other = { decryption: (src: string, keyWord: string) => { return decryption(src, keyWord); }, + sm2Encrypt: (msg: string, publicKey: string) => { + return sm2Encrypt(msg, publicKey); + }, base64Encrypt: (data: any) => { return base64Encrypt(data); }, diff --git a/src/views/home/widgets/components/calendar.vue b/src/views/home/widgets/components/calendar.vue index 88a1b1c..c3f9709 100644 --- a/src/views/home/widgets/components/calendar.vue +++ b/src/views/home/widgets/components/calendar.vue @@ -145,23 +145,23 @@ const changeSwitch = async (id: string) => { const initscheduleList = () => { // 初始化日程列表 - list({ - startDate: startDateRef.value, - endDate: endDateRef.value, - }).then((res) => { - // 获取返回结果的数据并转换为合适的格式 - reminders.value = res.data.map((item: any) => { - return { - key: item.id, - highlight: { - color: 'primary', - fillMode: 'outline', - }, - dates: item.scheduleDate, - customData: item, - }; - }); - }); + // list({ + // startDate: startDateRef.value, + // endDate: endDateRef.value, + // }).then((res) => { + // // 获取返回结果的数据并转换为合适的格式 + // reminders.value = res.data.map((item: any) => { + // return { + // key: item.id, + // highlight: { + // color: 'primary', + // fillMode: 'outline', + // }, + // dates: item.scheduleDate, + // customData: item, + // }; + // }); + // }); }; // 过滤日历中选中的单元格是否有日程