From 04783aad59b3e9694c33599f1c972327196577f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BF=9E=E5=AE=9D=E5=B1=B1?= <1253070437@qq.com> Date: Wed, 24 Dec 2025 16:33:48 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91=E6=95=B4?= =?UTF-8?q?=E4=BD=93=E4=BC=98=E5=8C=96=E5=89=8D=E5=90=8E=E7=AB=AF=E4=BA=A4?= =?UTF-8?q?=E4=BA=92=E7=9A=84=E7=99=BB=E5=BD=95=E6=80=A7=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=98=BE=E8=91=97=E6=8F=90=E5=8D=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- snowy-admin-web/src/views/auth/login/util.js | 7 +-- .../common/util/CommonCryptogramUtil.java | 30 +++++++--- .../login/service/impl/AuthServiceImpl.java | 58 ++++++++++++++----- 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/snowy-admin-web/src/views/auth/login/util.js b/snowy-admin-web/src/views/auth/login/util.js index 302eebc0..bb15b94e 100644 --- a/snowy-admin-web/src/views/auth/login/util.js +++ b/snowy-admin-web/src/views/auth/login/util.js @@ -11,12 +11,11 @@ import { globalStore } from '@/store' export const afterLogin = async (loginToken) => { const route = router.currentRoute.value const menuStore = useMenuStore() + const userStore = useUserStore() tool.data.set('TOKEN', loginToken) - // 初始化用户信息 - await useUserStore().initUserInfo() - // 获取用户的菜单 - await menuStore.fetchMenu() + // 并行初始化用户信息和获取用户的菜单 + await Promise.all([userStore.initUserInfo(), menuStore.fetchMenu()]) const menu = tool.data.get('MENU') let indexMenu = routerUtil.getIndexMenu(menu).path diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonCryptogramUtil.java b/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonCryptogramUtil.java index 2a2560f0..66e15c9a 100644 --- a/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonCryptogramUtil.java +++ b/snowy-common/src/main/java/vip/xiaonuo/common/util/CommonCryptogramUtil.java @@ -12,8 +12,12 @@ */ package vip.xiaonuo.common.util; +import cn.hutool.core.util.HexUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.SmUtil; +import cn.hutool.crypto.asymmetric.KeyType; +import cn.hutool.crypto.asymmetric.SM2; import com.antherd.smcrypto.sm2.Sm2; -import com.antherd.smcrypto.sm3.Sm3; import com.antherd.smcrypto.sm4.Sm4; import com.antherd.smcrypto.sm4.Sm4Options; import lombok.extern.slf4j.Slf4j; @@ -38,6 +42,9 @@ public class CommonCryptogramUtil { /** SM4的对称秘钥(生产环境需要改成自己使用的) 16 进制字符串,要求为 128 比特 */ private static final String KEY = "0123456789abcdeffedcba9876543210"; + /** Hutool SM2 对象 */ + private static final SM2 sm2 = SmUtil.sm2(HexUtil.decodeHex(PRIVATE_KEY), HexUtil.decodeHex(PUBLIC_KEY)); + /** * 加密方法(Sm2 的专门针对前后端分离,非对称秘钥对的方式,暴露出去的公钥,对传输过程中的密码加个密) * @@ -47,7 +54,7 @@ public class CommonCryptogramUtil { * @return 加密后的密文 */ public static String doSm2Encrypt(String str) { - return Sm2.doEncrypt(str, PUBLIC_KEY); + return sm2.encryptHex(str, KeyType.PublicKey); } /** @@ -60,8 +67,17 @@ public class CommonCryptogramUtil { * @return 解密后的明文 */ public static String doSm2Decrypt(String str) { - // 解密 - return Sm2.doDecrypt(str, PRIVATE_KEY); + try { + // 兼容性处理:Hutool要求密文以04开头(Uncompressed),如果前端传来的是不带04的(虽然sm-crypto默认带),则补上 + String text = str; + if (StrUtil.isNotBlank(text) && !text.startsWith("04")) { + text = "04" + text; + } + return sm2.decryptStr(text, KeyType.PrivateKey); + } catch (Exception e) { + // 降级处理:使用原版 antherd sm-crypto 解密(兼容性好但性能稍差) + return Sm2.doDecrypt(str, PRIVATE_KEY); + } } /** @@ -112,7 +128,7 @@ public class CommonCryptogramUtil { * @return 签名结果 */ public static String doSignature(String str) { - return Sm2.doSignature(str, PRIVATE_KEY); + return HexUtil.encodeHexStr(sm2.sign(StrUtil.utf8Bytes(str))); } /** @@ -125,7 +141,7 @@ public class CommonCryptogramUtil { * @return 是否通过 */ public static boolean doVerifySignature(String originalStr, String str) { - return Sm2.doVerifySignature(originalStr, str, PUBLIC_KEY); + return sm2.verify(StrUtil.utf8Bytes(originalStr), HexUtil.decodeHex(str)); } /** @@ -137,6 +153,6 @@ public class CommonCryptogramUtil { * @return hash 值 */ public static String doHashValue(String str) { - return Sm3.sm3(str); + return SmUtil.sm3(str); } } diff --git a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/impl/AuthServiceImpl.java b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/impl/AuthServiceImpl.java index bc76d77b..4b4b8f14 100644 --- a/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/impl/AuthServiceImpl.java +++ b/snowy-plugin/snowy-plugin-auth/src/main/java/vip/xiaonuo/auth/modular/login/service/impl/AuthServiceImpl.java @@ -48,6 +48,7 @@ import vip.xiaonuo.common.consts.CacheConstant; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.util.CommonCryptogramUtil; import vip.xiaonuo.common.util.CommonEmailUtil; +import java.util.concurrent.CompletableFuture; import vip.xiaonuo.common.util.CommonOtpUtil; import vip.xiaonuo.common.util.CommonTimeFormatUtil; import vip.xiaonuo.dev.api.DevConfigApi; @@ -703,13 +704,27 @@ public class AuthServiceImpl implements AuthService { List roleCodeList = roleList.stream().map(jsonObject -> jsonObject.getStr("code")).collect(Collectors.toList()); // 角色id和用户id集合 List userAndRoleIdList = CollectionUtil.unionAll(roleIdList, CollectionUtil.newArrayList(saBaseLoginUser.getId())); - // 获取按钮码 - saBaseLoginUser.setButtonCodeList(loginUserApi.getButtonCodeListListByUserAndRoleIdList(userAndRoleIdList)); - // 获取移动端按钮码 - saBaseLoginUser.setMobileButtonCodeList(loginUserApi.getMobileButtonCodeListListByUserIdAndRoleIdList(userAndRoleIdList)); - // 获取数据范围 - saBaseLoginUser.setDataScopeList(Convert.toList(SaBaseLoginUser.DataScope.class, - loginUserApi.getPermissionListByUserIdAndRoleIdList(userAndRoleIdList, saBaseLoginUser.getOrgId()))); + + // 并行获取信息 + CompletableFuture> buttonCodeListFuture = CompletableFuture.supplyAsync(() -> + loginUserApi.getButtonCodeListListByUserAndRoleIdList(userAndRoleIdList)); + CompletableFuture> mobileButtonCodeListFuture = CompletableFuture.supplyAsync(() -> + loginUserApi.getMobileButtonCodeListListByUserIdAndRoleIdList(userAndRoleIdList)); + CompletableFuture> permissionListFuture = CompletableFuture.supplyAsync(() -> + loginUserApi.getPermissionListByUserIdAndRoleIdList(userAndRoleIdList, saBaseLoginUser.getOrgId())); + try { + // 等待所有任务完成 + CompletableFuture.allOf(buttonCodeListFuture, mobileButtonCodeListFuture, permissionListFuture).join(); + // 获取按钮码 + saBaseLoginUser.setButtonCodeList(buttonCodeListFuture.get()); + // 获取移动端按钮码 + saBaseLoginUser.setMobileButtonCodeList(mobileButtonCodeListFuture.get()); + // 获取数据范围 + saBaseLoginUser.setDataScopeList(Convert.toList(SaBaseLoginUser.DataScope.class, permissionListFuture.get())); + } catch (Exception e) { + throw new CommonException("获取登录配置信息失败", e); + } + // 获取权限码 List permissionCodeList = saBaseLoginUser.getDataScopeList().stream() .map(SaBaseLoginUser.DataScope::getApiUrl).collect(Collectors.toList()); @@ -757,13 +772,28 @@ public class AuthServiceImpl implements AuthService { List roleCodeList = roleList.stream().map(jsonObject -> jsonObject.getStr("code")).collect(Collectors.toList()); // 角色id和用户id集合 List userAndRoleIdList = CollectionUtil.unionAll(roleIdList, CollectionUtil.newArrayList(saBaseClientLoginUser.getId())); - // 获取按钮码 - saBaseClientLoginUser.setButtonCodeList(clientLoginUserApi.getButtonCodeListListByUserAndRoleIdList(userAndRoleIdList)); - // 获取移动端按钮码 - saBaseClientLoginUser.setMobileButtonCodeList(clientLoginUserApi.getMobileButtonCodeListListByUserIdAndRoleIdList(userAndRoleIdList)); - // 获取数据范围 - saBaseClientLoginUser.setDataScopeList(Convert.toList(SaBaseClientLoginUser.DataScope.class, - clientLoginUserApi.getPermissionListByUserIdAndRoleIdList(userAndRoleIdList, null))); + + // 并行获取信息 + CompletableFuture> buttonCodeListFuture = CompletableFuture.supplyAsync(() -> + clientLoginUserApi.getButtonCodeListListByUserAndRoleIdList(userAndRoleIdList)); + CompletableFuture> mobileButtonCodeListFuture = CompletableFuture.supplyAsync(() -> + clientLoginUserApi.getMobileButtonCodeListListByUserIdAndRoleIdList(userAndRoleIdList)); + CompletableFuture> permissionListFuture = CompletableFuture.supplyAsync(() -> + clientLoginUserApi.getPermissionListByUserIdAndRoleIdList(userAndRoleIdList, null)); + + try { + // 等待所有任务完成 + CompletableFuture.allOf(buttonCodeListFuture, mobileButtonCodeListFuture, permissionListFuture).join(); + // 获取按钮码 + saBaseClientLoginUser.setButtonCodeList(buttonCodeListFuture.get()); + // 获取移动端按钮码 + saBaseClientLoginUser.setMobileButtonCodeList(mobileButtonCodeListFuture.get()); + // 获取数据范围 + saBaseClientLoginUser.setDataScopeList(Convert.toList(SaBaseClientLoginUser.DataScope.class, permissionListFuture.get())); + } catch (Exception e) { + throw new CommonException("获取登录配置信息失败", e); + } + // 获取权限码 List permissionCodeList = saBaseClientLoginUser.getDataScopeList().stream() .map(SaBaseClientLoginUser.DataScope::getApiUrl).collect(Collectors.toList());