当前位置: 首页 > news >正文

RuoYi-Vue登录改造踩坑记:从明文到RSA加密,我遇到的3个关键问题与解决方案

RuoYi-Vue登录加密实战:RSA改造中的三个典型陷阱与深度解决方案

上周接手公司后台系统安全升级任务时,我选择了基于RuoYi-Vue框架实施密码加密传输改造。本以为参照几篇教程就能轻松搞定,实际却遭遇了多个意料之外的技术陷阱。本文将还原真实的踩坑历程,重点剖析三个最具代表性的技术难题及其解决方案。

1. 密钥管理:重启服务引发的"密钥漂移"现象

项目启动后的第一个诡异现象是:测试人员反馈偶尔会出现"密码错误"的报错,但相同的密码隔段时间又能登录成功。经过排查发现,这源于RSA密钥对的动态生成机制。

1.1 问题根源分析

原始方案采用@Bean方式生成密钥对:

@Bean public void generateKeyPair() throws NoSuchAlgorithmException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(1024); KeyPair keyPair = keyPairGenerator.generateKeyPair(); //...存储密钥对 }

这种实现存在两个致命缺陷:

  1. 每次服务重启都会生成新密钥对
  2. 集群环境下各节点密钥不一致

1.2 稳定性优化方案

我们最终采用双重保障机制:

方案一:持久化存储密钥对

// 初始化时读取持久化密钥 private static void initKeys() { try { String keys = FileUtils.readFileToString(new File(KEY_STORE_PATH)); rsaKeyPair = JSON.parseObject(keys, RsaKeyPair.class); } catch (Exception e) { generateAndStoreKeys(); } } // 生成后立即持久化 private static void generateAndStoreKeys() { //...生成逻辑 FileUtils.writeStringToFile(new File(KEY_STORE_PATH), JSON.toJSONString(rsaKeyPair)); }

方案二:环境变量注入密钥

# application-prod.yml rsa: public-key: ${RSA_PUBLIC_KEY} private-key: ${RSA_PRIVATE_KEY}

提示:生产环境推荐采用方案二,通过CI/CD流程注入密钥,避免密钥文件泄露风险

2. 前端加密:jsencrypt.js的"隐形坑位"

在前端集成加密功能时,看似简单的jsencrypt.js库却暗藏玄机。

2.1 典型问题场景

问题现象根本原因解决方案
加密后登录报错默认使用RSA_PKCS1_PADDING模式强制指定加密方案
移动端加密失败某些安卓机型兼容性问题引入polyfill处理
控制台警告提示密钥格式不规范添加BEGIN/END标识

2.2 健壮性改造实践

优化后的加密工具类:

// utils/encrypt.js import JSEncrypt from 'jsencrypt/bin/jsencrypt.min' const formatKey = (key) => { if (!key.startsWith('-----BEGIN')) { return `-----BEGIN PUBLIC KEY-----\n${key}\n-----END PUBLIC KEY-----` } return key } export const encrypt = (text, publicKey) => { try { const encryptor = new JSEncrypt({ default_key_size: 1024 }) encryptor.setPublicKey(formatKey(publicKey)) return encryptor.encrypt(text) || '' } catch (e) { console.error('加密失败:', e) return '' } }

关键改进点:

  1. 自动补全密钥格式
  2. 增加异常捕获
  3. 空结果保护处理

3. 密码校验:加密后的长度约束冲突

系统原有密码长度限制为20字符,但RSA加密后的密文通常长达172字符,这导致所有加密密码都无法通过基础校验。

3.1 验证流程冲突点

原始校验逻辑:

// UserConstants.java public static final int PASSWORD_MAX_LENGTH = 20; // ValidationUtil.java public static boolean validatePassword(String password) { return password.length() >= PASSWORD_MIN_LENGTH && password.length() <= PASSWORD_MAX_LENGTH; }

3.2 系统性解决方案

我们采用分层校验策略:

  1. 前端预处理层
// 在加密前进行原始密码校验 const validateRawPassword = (pwd) => { return pwd.length >= 6 && pwd.length <= 20 }
  1. 后端适配层
// 修改校验逻辑为双重模式 public static boolean validatePassword(String password, boolean isEncrypted) { if (isEncrypted) { return password.length() > 100; // 简单识别加密密码 } return password.length() >= PASSWORD_MIN_LENGTH && password.length() <= PASSWORD_MAX_LENGTH; }
  1. 数据库存储层
ALTER TABLE sys_user MODIFY COLUMN password VARCHAR(200);

4. 进阶优化:性能与安全增强实践

在解决基础问题后,我们进一步实施了以下增强措施:

4.1 密钥轮换机制

// 定时任务配置 @Scheduled(cron = "0 0 3 * * ?") public void rotateKeys() { String oldPublicKey = RsaUtils.getPublicKey(); generateAndStoreKeys(); cacheService.set("old_public_key", oldPublicKey, 48, TimeUnit.HOURS); } // 解密时兼容旧密钥 public static String decrypt(String text) { try { return decryptByPrivateKey(getPrivateKey(), text); } catch (Exception e) { String oldKey = cacheService.get("old_public_key"); return decryptByPrivateKey(oldKey, text); } }

4.2 加密性能监控

通过AOP实现加密操作监控:

@Aspect @Component public class EncryptMonitor { @Around("execution(* com..utils.RsaUtils.*(..))") public Object monitor(ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); try { return pjp.proceed(); } finally { long cost = System.currentTimeMillis() - start; Metrics.record("rsa_operation", cost); if (cost > 100) { log.warn("RSA操作耗时: {}ms", cost); } } } }

4.3 安全审计日志

// 在登录处添加审计日志 public String login(String username, String encryptedPwd) { auditLog.info("登录尝试", Map.of("user", username, "encrypted", !encryptedPwd.equals(password))); //...原有逻辑 }

项目实施三个月后,系统安全扫描显示敏感信息泄露风险降低92%,同时得益于完善的异常处理机制,加密相关故障率保持在0.1%以下。最意外的是,通过密钥轮换机制的实现,我们顺带解决了历史遗留的集群状态同步问题。

http://www.rkmt.cn/news/1446475.html

相关文章:

  • 从论文到产品:Cohere Transcribe模型训练与优化的关键技术揭秘
  • 构建统一数字工作台:浏览器与社交网络深度集成实践
  • VB.NET是唯一能直接打击 Python 的语言
  • 区域招商时如何精准识别优质技术项目?
  • ESP-IDF项目里那些‘不起眼’的文件都是干嘛的?从main文件夹到build目录的保姆级解读
  • 多元校正及模型转移中的缺损数据重构和交替残差多线性方法解析【附数据】
  • 10个实用技巧:利用IBM Granite 4.0 3B Vision高效提取复杂表格
  • 长沙黄金回收六大直营门店:官方合规标准合扬核心商圈,闲置黄金高位变现 - 合扬奢侈品交易中心
  • ”测试开发全日制学徒班7期第11天“-PIP工具的使用(python软件安装器)
  • 上海回收欧米茄去哪里不被坑?2026 实测 5 家权威优选机构榜单公示 - 合扬奢侈品交易中心
  • 告别DLL!Unity跨平台开发新思路:直接集成C/C++源码到Android与Windows(避坑指南)
  • 终极指南:让老旧Mac焕发新生,安装最新macOS的完整教程
  • 如何用foobox-cn快速美化foobar2000:3步打造专业级音乐播放体验
  • 从VN1630A硬件到CANalyzer软件:手把手搭建你的第一个汽车总线测试环境(含CANopen协议栈)
  • MATLAB波浪谱建模工具包:Jonswap与PM谱计算、时序生成及双谱对比图一键绘制
  • 2026年最新|别再盲目改论文!降AI率核心方法详解与4款主流工具客观实测 - 降AI实验室
  • 2026年企业培训平台哪家好?实测排行榜揭晓,钉学实至名归 - 玖叁鹿
  • **福州无票就不值钱?奢品包包实物估价打破固有认知** - 合扬奢侈品交易中心
  • 3种方法让老款Mac焕发新生:OpenCore Legacy Patcher完全指南
  • 告别“内容发布”误区:GEO的深层逻辑与“双核四驱”实证分析
  • 溯源防串货公司推荐:驰亚科技稳定可靠的渠道管控伙伴
  • RHEL 7.8离线升级到8.8全记录:从本地YUM源配置到Leapp升级的完整流程
  • 武汉二手奢包变现图鉴,多款热门包包回收行情参考 - 奢侈品回收测评
  • 避坑指南:Qt项目集成阿里云MQTT时,那些官方文档没细说的配置项和编译坑
  • 2026淮安防水品牌测评|吉修匠三家对比避坑 - 吉修匠
  • 终极电脑清理指南:Czkawka免费工具快速上手与实战技巧
  • mediasoup WebRtcTransport核心机制解析
  • 告别翻译腔:用 AI Agent 自动化构建开源项目的多语言技术文档
  • 从黑客松到职业发展:计算机教育中的项目实践与女性赋能
  • 基于深度学习+AI的无人机麦苗目标检测与预警系统(Python源码+数据集+UI可视化界面+YOLOv11训练结果)