ruoyi-vue框架密码加密传输

先看一下改造后的样子,输入的密码不会再以明文展示。

下面我主要把前后端改造的代码贴出来。

1.后端代码

RsaUtils类

在com.ruoyi.common.utils包下新建RsaUtils类,RsaUtils添加了@Component注解 generateKeyPair()构建密钥对添加了@Bean注解 在项目启动时通过@Bean的方式将普通类事例化到spring容器中 所以在系统启动后 每次调用接口会是一样的公私秘钥 每次重启后公私钥不同

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;@Component
public class RsaUtils {// Rsa 私钥 也可固定秘钥对 若依原写法(不安全)public static String privateKeys = "";private static String publicKeyStr = "";private static String privateKeyStr = "";private static final RsaKeyPair rsaKeyPair = new RsaKeyPair();private static final Logger logger = LoggerFactory.getLogger(RsaUtils.class);/*** 私钥解密** @param text 待解密的文本* @return 解密后的文本*/public static String decryptByPrivateKey(String text) throws Exception {
//        logger.info(rsaKeyPair.getPrivateKey());return decryptByPrivateKey(rsaKeyPair.getPrivateKey(), text);}/*** 公钥解密** @param publicKeyString 公钥* @param text            待解密的信息* @return 解密后的文本*/public static String decryptByPublicKey(String publicKeyString, String text) throws Exception {X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, publicKey);byte[] result = cipher.doFinal(Base64.decodeBase64(text));return new String(result);}/*** 私钥加密** @param privateKeyString 私钥* @param text             待加密的信息* @return 加密后的文本*/public static String encryptByPrivateKey(String privateKeyString, String text) throws Exception {PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, privateKey);byte[] result = cipher.doFinal(text.getBytes());return Base64.encodeBase64String(result);}/*** 私钥解密** @param privateKeyString 私钥* @param text             待解密的文本* @return 解密后的文本*/public static String decryptByPrivateKey(String privateKeyString, String text) throws Exception {PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] result = cipher.doFinal(Base64.decodeBase64(text));return new String(result);}/*** 公钥加密** @param publicKeyString 公钥* @param text            待加密的文本* @return 加密后的文本*/public static String encryptByPublicKey(String publicKeyString, String text) throws Exception {X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] result = cipher.doFinal(text.getBytes());return Base64.encodeBase64String(result);}/*** 构建RSA密钥对** @return 生成后的公私钥信息*/@Beanpublic void generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(1024);KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());rsaKeyPair.setPrivateKey(privateKeyString);rsaKeyPair.setPublicKey(publicKeyString);publicKeyStr = publicKeyString;privateKeyStr = privateKeyString;}public static String getPublicKey() {return publicKeyStr;}public static String getPrivateKey() {return privateKeyStr;}public static RsaKeyPair rsaKeyPair() {return rsaKeyPair;}/*** RSA密钥对对象*/public static class RsaKeyPair {private String publicKey;private String privateKey;public void setPublicKey(String publicKey) {this.publicKey = publicKey;}public void setPrivateKey(String privateKey) {this.privateKey = privateKey;}public RsaKeyPair() {}public RsaKeyPair(String publicKey, String privateKey) {this.publicKey = publicKey;this.privateKey = privateKey;}public String getPublicKey() {return publicKey;}public String getPrivateKey() {return privateKey;}}
}

在SysLoginController添加获取公钥接口

/*** 获取公钥 前端用来密码加密** @return*/@GetMapping("/publicKey")public RsaUtils.RsaKeyPair publicKey() {return RsaUtils.rsaKeyPair();}

修改SysLoginService类中的login方法

/*** 登录验证** @param username 用户名* @param password 密码* @param code 验证码* @param uuid 唯一标识* @return 结果*/public String login(String username, String password, String code, String uuid){// 验证码校验validateCaptcha(username, code, uuid);// 登录前置校验loginPreCheck(username, password);// 用户验证Authentication authentication = null;try{//RsaUtils.decryptByPrivateKey(password)解密密码UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,  RsaUtils.decryptByPrivateKey(password));AuthenticationContextHolder.setContext(authenticationToken);// 该方法会去调用UserDetailsServiceImpl.loadUserByUsernameauthentication = authenticationManager.authenticate(authenticationToken);}catch (Exception e){if (e instanceof BadCredentialsException){AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));throw new UserPasswordNotMatchException();}else{AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));throw new ServiceException(e.getMessage());}}finally{AuthenticationContextHolder.clearContext();}AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));LoginUser loginUser = (LoginUser) authentication.getPrincipal();recordLoginInfo(loginUser.getUserId());// 生成tokenreturn tokenService.createToken(loginUser);}

修改重置密码

/*** 重置密码*/@Log(title = "个人信息", businessType = BusinessType.UPDATE)@PutMapping("/updatePwd")public AjaxResult updatePwd(String oldPassword, String newPassword) throws Exception {LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());String userName = loginUser.getUsername();//加密后的String password = loginUser.getPassword();//解密oldPassword = RsaUtils.decryptByPrivateKey(oldPassword);newPassword = RsaUtils.decryptByPrivateKey(newPassword);//拿原密码和加密后的解密if (!SecurityUtils.matchesPassword(oldPassword, password)) {return AjaxResult.error("修改密码失败,旧密码错误");}if (SecurityUtils.matchesPassword(newPassword, password)) {return AjaxResult.error("新密码不能与旧密码相同");}if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) {// 更新缓存用户密码loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));tokenService.setLoginUser(loginUser);return AjaxResult.success();}return AjaxResult.error("修改密码异常,请联系管理员");}

在SecurityConfig中添加获取公钥接口

因为密码校验时会校验长度,加密后的密码会超出框架内原来设定的长度,修改UserConstants类中的PASSWORD_MAX_LENGTH

2.前端代码变动

jsencrypt.js

import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'// 密钥对生成 http://web.chacuo.net/netrsakeypair//const publicKey = ''//const privateKey = ''// 加密
export function encrypt(txt, publicKey) {const encryptor = new JSEncrypt()encryptor.setPublicKey(publicKey) // 设置公钥return encryptor.encrypt(txt) // 对数据
}// 解密(暂无使用)
export function decrypt(txt) {const encryptor = new JSEncrypt()encryptor.setPrivateKey(privateKey) // 设置私钥return encryptor.decrypt(txt) // 对数据进行解密
}

login.js添加获取公钥路由

// 获取key
export function getPublicKey() {return request({url: '/publicKey',method: 'get',})
}

user.js修改登入方法,方便copy我直接全放进来了

import { login, logout, getInfo,getPublicKey } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { encrypt, decrypt } from '@/utils/jsencrypt'const user = {state: {token: getToken(),id: '',name: '',avatar: '',roles: [],permissions: []},mutations: {SET_TOKEN: (state, token) => {state.token = token},SET_ID: (state, id) => {state.id = id},SET_NAME: (state, name) => {state.name = name},SET_AVATAR: (state, avatar) => {state.avatar = avatar},SET_ROLES: (state, roles) => {state.roles = roles},SET_PERMISSIONS: (state, permissions) => {state.permissions = permissions}},actions: {getPublicKey() {return new Promise((resolve, reject) => {getPublicKey().then(res => {resolve(res)}).catch(error => {reject(error)})})},// 登录Login({ commit, dispatch }, userInfo) {return new Promise((resolve, reject) => {dispatch('getPublicKey').then(res => {let publicKey = res.publicKeyconst username = userInfo.username.trim()//调用加密方法(传密码和公钥)const password = encrypt(userInfo.password, publicKey)const code = userInfo.codeconst uuid = userInfo.uuidlogin(username, password, code, uuid).then(res => {setToken(res.token)commit('SET_TOKEN', res.token)resolve()}).catch(error => {reject(error)})})})},// 获取用户信息GetInfo({ commit, state }) {return new Promise((resolve, reject) => {getInfo().then(res => {const user = res.userconst avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar;if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组commit('SET_ROLES', res.roles)commit('SET_PERMISSIONS', res.permissions)} else {commit('SET_ROLES', ['ROLE_DEFAULT'])}commit('SET_ID', user.userId)commit('SET_NAME', user.userName)commit('SET_AVATAR', avatar)resolve(res)}).catch(error => {reject(error)})})},// 退出系统LogOut({ commit, state }) {return new Promise((resolve, reject) => {logout(state.token).then(() => {commit('SET_TOKEN', '')commit('SET_ROLES', [])commit('SET_PERMISSIONS', [])removeToken()resolve()}).catch(error => {reject(error)})})},// 前端 登出FedLogOut({ commit }) {return new Promise(resolve => {commit('SET_TOKEN', '')removeToken()resolve()})}}
}export default user

resetPwd.vue

methods: {getPublicKey() {return new Promise((resolve, reject) => {getPublicKey().then(res => {resolve(res)}).catch(error => {reject(error)})})},submit() {this.$refs["form"].validate(valid => {if (valid) {this.getPublicKey().then(res=>{let publicKey = res.publicKeyconsole.log("res.publicKey",res.publicKey)const oldPassword = encrypt(this.user.oldPassword, publicKey)const newPassword = encrypt(this.user.newPassword, publicKey)updateUserPwd(oldPassword, newPassword).then(response => {this.msgSuccess("修改成功");});})}});},close() {this.$store.dispatch("tagsView/delView", this.$route);this.$router.push({ path: "/index" });}}

这样就完成改造了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/726440.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大语言模型系列-GPT-2

文章目录 前言一、GPT-2做的改进二、GPT-2的表现总结 前言 《Language Models are Unsupervised Multitask Learners,2019》 前文提到,GPT-1利用不同的模型结构微调初步解决了多任务学习的问题,但是仍然是预训练微调的形式,GPT-…

【Spring高级】第2讲:容器实现类

目录 BeanFactory实现BeanDefinition后置处理器单例bean创建后置处理器顺序总结 ApplicationContext实现ClassPathXmlApplicationContextFileSystemXmlApplicationContextAnnotationConfigApplicationContextAnnotationConfigServletWebServerApplicationContext BeanFactory实…

Ubuntu环境配置-LinuxQQ篇

本教程下载Linux QQ的版本是linuxqq_3.0.0-571_amd64.deb 一、下载LinuxQQ 直接使用wget命令下载链接,下载文件 wget https://dldir1.qq.com/qqfile/qq/QQNT/c005c911/linuxqq_3.0.0-571_amd64.deb 二、安装LinuxQQ 当下载完成后,运行命令:…

图像锐化-拉普拉斯算子 Sobel算子

算子解释 广义的讲,对任何函数进行某一项操作都可以认为是一个算子,甚至包括求幂次,开方都可以认为是一个算子,只是有的算子我们用了一个符号来代替他所要进行的运算罢了,所以大家看到算子就不要纠结,他和f…

Sentinel 规则持久化,基于Redis持久化【附带源码】

B站视频讲解 学习链接🔗 文章目录 一、理论二、实践2-1、dashboard 请求Redis2-1-1、依赖、配置文件引入2-1-2、常量定义2-1-3、改写唯一id2-1-4、新Provider和Publisher2-1-5、改写V2 2-2、应用服务改造2-2-1、依赖、配置文件引入2-2-2、注册监听器 三、源码获取3…

Talk|加州大学圣地亚哥分校程旭欣:视觉反馈下足式机器人的全身操作与运动

本期为TechBeat人工智能社区第576期线上Talk。 北京时间3月6日(周三)20:00,加州大学圣地亚哥分校博士生—程旭欣的Talk已准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “视觉反馈下足式机器人的全身操作与运动”,向大家系统地介绍…

智能驾驶规划控制理论学习07-规划算法整体框架

一、解耦合策略 1、路径-速度解耦策略概述 路径-速度解耦指的是将车辆的运动分成路径规划和速度规划两部分,对两个部分分别进行研究。 路径规划: 假设环境是“静态的”,将障碍物投射到参考路径上,并规划一条避开它们的路径&…

【C语言】linux内核napi_gro_receive和netif_napi_add

napi_gro_receive 一、注释 // napi_gro_receive是网络设备接口的一个函数,它被NAPI(New API)网络轮询机制使用,用于接收和处理接收到的数据包。 // 这个函数通过通用接收分组(GRO,Generic Receive Offlo…

Ubuntu安装conda以后,给jupyter安装C++内核

前言 大家都知道,jupyter notebook 可以支持python环境,可以在不断点调试的情况下,打印出当前结果,如果代码错了也不影响前面的内容。于是我就想有没有C环境的,结果还真有。 参考文章: 【分享】Ubuntu安装…

【金三银四的季节看下Java ORM的走向和性能对比】总结

写在最后 经过将近一周时间的框架收集、学习、实验、编码、测试市面上常见的ORM框架,过程中拜读了很多作者的博文、样例,学习很多收获很多。 重新梳理下整理的框架:mybatis-plus、lazy、sqltoy、mybatis-flex、easy-query、mybatis-mp、jpa、…

什么是工业交换机?

如今,工业交换机在能源、环保、交通、智慧城市监控等各个行业都发挥着至关重要的作用,其需求也日益增长。本文将全面介绍工业交换机,帮助你进一步加深了解。 什么是工业交换机? 工业交换机,又称工业以太网交换机&…

《探索自动驾驶技术的前景与挑战》

自动驾驶技术,作为现代科技的一大突破,正逐渐改变着我们的交通方式、生活方式以及整个社会结构。本文将围绕自动驾驶技术的现状、优势、局限性以及未来发展趋势展开探讨。 自动驾驶技术的现状概述 自动驾驶技术作为当今科技领域的一项前沿技术,已经取得了巨大的进展并在不同…

安卓开发之资源概述、优劣分析与优化方案

摘要 随着智能手机的普及,Android操作系统已成为全球最广泛使用的移动平台之一。在Android应用开发中,资源管理是构建高效、响应迅速且用户友好的应用程序的关键要素。 本文主要探讨了安卓应用程序开发过程中的资源管理机制,包括其基本结构、…

一键清除JavaScript代码中的注释:使用正则表达式实现

这个正则表达式可以有效地匹配 JavaScript 代码中的各种注释&#xff0c;并且跳过了以 http: 或 https: 开头的链接。 /\/\*[\s\S]*?\*\/|\/\/[^\n]*|<!--[\s\S]*?-->|(?<!http:|https:)\/\/[^\n]*/gvscode 实战&#xff0c;ctrlF 调出查找替换工具&#xff0c;点…

如何把网页调用变为代码调用

1.背景 最近有一个需求&#xff0c;猜测一段十六进制流的校验方式&#xff0c;挨个尝试非常耗时&#xff0c;需要写代码&#xff0c;调用网页上的功能。 2.解决方案 可以使用Python的 requests 库来发起HTTP请求&#xff0c;并通过POST请求将数据发送给服务器进行计算CRC校验和…

【备战蓝桥杯系列】Java组国二选手笔记一:蓝桥杯中的常用语法特性

蓝桥杯Java国二选手笔记一&#xff1a;蓝桥杯中的常用语法特性 前言 参加了好几次蓝桥杯了&#xff0c;C组参加了&#xff0c;Java也参加过&#xff0c;也会用python刷算法。下面给出常用的Java语法特性在蓝桥杯中的使用&#xff0c;以及常见的需要注意的Java语法规范。有准备…

【MySQL】-知识点整理

1、存储引擎 -- 查询数据库支持的存储引擎 show engines; -- 查询当前数据库使用的存储引擎 show variables like %storage_engines%; 主要的存储引擎说明&#xff1a; 1&#xff09;MyISAM&#xff1a;无外键、表锁、所有索引都是非聚簇索引、无事务、记录表总条数、删除表…

基于el-tree实现懒加载穿梭条

一、关键代码 <template><div><!-- 左侧待选列表 --><div class"left-box"><p>待选列表</p><el-input placeholder"输入关键词过滤" v-model"leftFilterText" clearable/><el-treeref"tree…

便捷在线导入:完整Axure元件库集合,让你的设计更高效!

Axure元件库包含基本的工具组件&#xff0c;可以使原型绘制节省大量的重复工作&#xff0c;保持整个设计页面的一致性和标准化&#xff0c;同时显得专业。Axure元件库就像我们日常生活中的门把手、自行车踏板和桌子上的螺丝钉&#xff0c;需要组装才能使用。作为一名成熟的产品…

【Web - 框架 - Vue】随笔 - Vue的简单使用(02) - 快速上手

【Web - 框架 - Vue】随笔 - Vue的简单使用(02) - 快速上手 Vue模板代码 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Vue模板</title> </head> <body> <div id"…