jeecg spring数据源用户名和密码加密 避免明文安全漏洞

news2024/11/18 11:18:41

1.目的

由于系统部署在互联网,配置文件中的数据库账号密码使用明文,存在安全隐患,做等保测试时要求对其加密。

2.实现方法

Jeecg框架本身有PasswordUtil可以使用PBEWITHMD5andDES进行加密,这里为方便改造,且安全性较高,故选择使用此加密方式进行加密。
附:PasswordUtil代码

package org.jeecgframework.core.util;

import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
public class PasswordUtil {

	/**
	 * JAVA6支持以下任意一种算法 PBEWITHMD5ANDDES PBEWITHMD5ANDTRIPLEDES
	 * PBEWITHSHAANDDESEDE PBEWITHSHA1ANDRC2_40 PBKDF2WITHHMACSHA1
	 * */

	/**
	 * 定义使用的算法为:PBEWITHMD5andDES算法
	 */
	public static final String ALGORITHM = "PBEWithMD5AndDES";//加密算法
	public static final String Salt = "63293188";//密钥

	/**
	 * 定义迭代次数为1000次
	 */
	private static final int ITERATIONCOUNT = 1000;

	/**
	 * 获取加密算法中使用的盐值,解密中使用的盐值必须与加密中使用的相同才能完成操作. 盐长度必须为8字节
	 * 
	 * @return byte[] 盐值
	 * */
	public static byte[] getSalt() throws Exception {
		// 实例化安全随机数
		SecureRandom random = new SecureRandom();
		// 产出盐
		return random.generateSeed(8);
	}

	public static byte[] getStaticSalt() {
		// 产出盐
		return Salt.getBytes();
	}

	/**
	 * 根据PBE密码生成一把密钥
	 * 
	 * @param password
	 *            生成密钥时所使用的密码
	 * @return Key PBE算法密钥
	 * */
	private static Key getPBEKey(String password) {
		// 实例化使用的算法
		SecretKeyFactory keyFactory;
		SecretKey secretKey = null;
		try {
			keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
			// 设置PBE密钥参数
			PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
			// 生成密钥
			secretKey = keyFactory.generateSecret(keySpec);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return secretKey;
	}

	/**
	 * 加密明文字符串
	 * 
	 * @param plaintext
	 *            待加密的明文字符串
	 * @param password
	 *            生成密钥时所使用的密码
	 * @param salt
	 *            盐值
	 * @return 加密后的密文字符串
	 * @throws Exception
	 */
	public static String encrypt(String plaintext, String password, byte[] salt) {

		Key key = getPBEKey(password);
		byte[] encipheredData = null;
		PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, ITERATIONCOUNT);
		try {
			Cipher cipher = Cipher.getInstance(ALGORITHM);

			cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);

			encipheredData = cipher.doFinal(plaintext.getBytes());
		} catch (Exception e) {
		}
		return bytesToHexString(encipheredData);
	}

	/**
	 * 解密密文字符串
	 * 
	 * @param ciphertext
	 *            待解密的密文字符串
	 * @param password
	 *            生成密钥时所使用的密码(如需解密,该参数需要与加密时使用的一致)
	 * @param salt
	 *            盐值(如需解密,该参数需要与加密时使用的一致)
	 * @return 解密后的明文字符串
	 * @throws Exception
	 */
	public static String decrypt(String ciphertext, String password, byte[] salt) {

		Key key = getPBEKey(password);
		byte[] passDec = null;
		PBEParameterSpec parameterSpec = new PBEParameterSpec(getStaticSalt(), ITERATIONCOUNT);
		try {
			Cipher cipher = Cipher.getInstance(ALGORITHM);

			cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);

			passDec = cipher.doFinal(hexStringToBytes(ciphertext));
		}

		catch (Exception e) {
			// TODO: handle exception
		}
		return new String(passDec);
	}

	/**
	 * 将字节数组转换为十六进制字符串
	 * 
	 * @param src
	 *            字节数组
	 * @return
	 */
	public static String bytesToHexString(byte[] src) {
		StringBuilder stringBuilder = new StringBuilder("");
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}

	/**
	 * 将十六进制字符串转换为字节数组
	 * 
	 * @param hexString
	 *            十六进制字符串
	 * @return
	 */
	public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	public static void main(String[] args) {
		int i=10;
		for (int j = 0; j < i; j++) {
			if((j)%3==0)
			{
				System.out.print("<br>");
			}
			else {
				System.out.print(j);
			}
		}
		System.out.print(-1%2==0);
		String str = "root";
		String password = "root";

		org.jeecgframework.core.util.LogUtil.info("明文:" + str);
		org.jeecgframework.core.util.LogUtil.info("密码:" + password);

		try {
			byte[] salt = PasswordUtil.getStaticSalt();
			String ciphertext = PasswordUtil.encrypt(str, password, salt);
			org.jeecgframework.core.util.LogUtil.info("密文:" + ciphertext);
			String plaintext = PasswordUtil.decrypt(ciphertext, password, salt);
			org.jeecgframework.core.util.LogUtil.info("明文:" + plaintext);
			
			String result = PasswordUtil.decrypt("ea3d519525358e00", "root", salt);
			org.jeecgframework.core.util.LogUtil.info("明文:" + result);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
2.1、加密方式

先通过加密方法把将要加密的数据进行加密,我这边是对数据库用户名和密码都加密处理
在这里插入图片描述
加密后数据库配置文件
在这里插入图片描述

2.2 spring-mvc-hibernate.xml中配置并添加一个类继承PropertyPlaceholderConfigurer实现使用加密字符串,使用时解密

在这里插入图片描述
EncryptPropertyPlaceholderConfigurer.java

package org.jeecgframework.core.config;

import org.apache.commons.lang.ObjectUtils;
import org.jeecgframework.core.util.PasswordUtil;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

public class EncryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
    /** 需要解密的字段 */
    private String[] encryptPropNames = { "jdbc.username.jeecg", "jdbc.password.jeecg" };
//    private String[] encryptPropNames = {  "jdbc.password.jeecg" };

    protected String convertProperty(String propertyName, String propertyValue) {
        if (isEncryptProp(propertyName)) {
            // 解密(根据实际内容改成具体解密方法)
            return PasswordUtil.decrypt(propertyValue,"password",PasswordUtil.getStaticSalt());
        } else {
            return propertyValue;
        }
    }

    /**
     * 判断属性是否需要解密
     *
     * @param propertyName
     * @return
     */
    @SuppressWarnings("deprecation")
    private boolean isEncryptProp(String propertyName) {
        for (String encryptpropertyName : encryptPropNames) {
            if (ObjectUtils.equals(encryptpropertyName, propertyName)) {
                return true;
            }
        }
        return false;
    }
}

不详之处可参考:sping数据源中使用加密的用户名和密码

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

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

相关文章

andrio复习

第2章 Android常见界面布局 View View与ViewGroup View&#xff1a;按钮&#xff08;Button&#xff09;、文本框&#xff08;TextView&#xff09;和图像视图&#xff08;ImageView&#xff09;等 ViewGroup&#xff1a;LinearLayout、RelativeLayout、FrameLayout等都是Vi…

智慧校园综合解决方案:提供全方位的学校管理支持

在当今数字化时代&#xff0c;学校管理面临着越来越多的挑战&#xff0c;包括学生管理、教职员工管理、校园安全等。为了应对这些挑战&#xff0c;智慧校园综合解决方案应运而生。智慧校园综合解决方案融入了先进的信息技术&#xff0c;为学校带来了一场管理与教育模式的革新。…

欢迎 Stable Diffusion 3 加入 Diffusers

作为 Stability AI 的 Stable Diffusion 家族最新的模型&#xff0c;Stable Diffusion 3(SD3) 现已登陆 Hugging Face Hub&#xff0c;并且可用在 &#x1f9e8; Diffusers 中使用了。 Stable Diffusion 3https://stability.ai/news/stable-diffusion-3-research-paper 当前放出…

为什么Mid journey很容易就能做出很有氛围感的图而SD却容易做图很丑?

前言 6月12日&#xff0c;Midjourney更新了一项新的功能——模型个性化&#xff0c;这一项功能最重要的作用就是能够让生成的图像更加符合你自己的审美标准。就像每个艺术家都有自己的独特风格一样&#xff0c;有了这项模型个性化功能的加持&#xff0c;每个人都能生成具有鲜明…

Mcgs屏幕脚本程序

目录 1.脚本程序概述1.1 脚本程序简介1.2 脚本程序编辑环境 2.脚本程序语言要素2.1 变量和常量2.2 对象2.3 事件2.4 表达式2.5 联行符2.6 运算符2.7 系统函数 3. 基本语句3.1 赋值语句3.2 条件语句3.3 循环语句3.4 跳出语句3.5 退出语句3.6 注释语句3.7 声明语句3.6 命名规则 1…

uniapp运行到模拟器(联想模拟器)

记录一下uniapp项目运行到联想模拟器的流程 先配置一下模拟器端口 填写对应的adb路径&#xff0c;也就是模拟器安装路径下的adb.exe的路径 然后打开模拟器的设置&#xff0c;搜索版本找到版本号&#xff0c;多次点击打开开发者模式 进入开发者选项&#xff0c;打开USB调试 …

睿治数据治理平台焕新升级,推出全新建模与调度平台

在数据治理的浩瀚征途中&#xff0c;企业常常面临着数据冗余如同连绵山峦&#xff0c;使得关键信息的获取变得困难重重&#xff1b;在数据检索的海洋中&#xff0c;有时迷失方向&#xff0c;消耗大量时间精力&#xff0c;严重影响了运营效率&#xff1b;特别是在处理大规模数据…

开辟一个存储空间以存放一个结构体数据

在软件开发中&#xff0c;常常需要动态地分配和撤销内存空间&#xff0c;例如对动态链表中结点的插入与删除。在C语言中是利用库函数malloc和free来分配和撤销内存空间的。C提供了较简便而功能较强的运算符new和delete 来取代malloc和free函数。注意&#xff1a;new和delete是运…

一次完整的web渗透测试(文件上传getshell)

一、背景 日常空闲事件会进行一些公益SRC的挖掘&#xff0c;今天也是空闲&#xff0c;摸鱼有点浪费时间&#xff0c;那就拿几个公益SRC练练手&#xff08;有waf的我会直接跳过&#xff0c;毕竟没钱去挂代理&#xff09;。上号&#xff01; 二、测试过程 2.1、目录扫描 先给…

Webmin在EPICS IOC启动中的应用

本文使用webmin启动远程工控机中的EPICS IOC&#xff0c;受控设备使用PI公司的六轴台以及相应的控制器C-887&#xff1a; 1&#xff09;控制器C-887 2) 六轴台&#xff1a; 3&#xff09;在工控机上安装用于与C-887控制器进行通信的EPICS IOC程序&#xff0c;安装结束后&#…

哪个城市的Delphier最多?Delphier平均年龄多大了?

先来看看哪个城市的Delphier最多&#xff1a; 北上广深不是白叫的&#xff0c; 大家想换工作&#xff0c;就去这些大城市&#xff0c;机会多。 有人会觉得奇怪&#xff0c;怎么才这么几个人&#xff1f; 因为以上数据统计基数为2000人&#xff0c; 根据微信公众号和QQ群得出…

基于jeecgboot-vue3的Flowable流程-业务表单

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 这个部分主要讲自定义业务表单的流程关联 1、挂接关联流程对话框代码 <!--挂载关联流程--><a-modal cancel"flowOpen false" :title"flowTitle" v-model:…

Linux系统:线程互斥

Linux系统&#xff1a;线程互斥 线程互斥互斥锁 mutex互斥锁原理 常见的锁死锁自旋锁 spinlock其它锁 线程互斥 讲解线程互斥前&#xff0c;先看到一个抢票案例&#xff1a; class customer { public:int _ticket_num 0;pthread_t _tid;string _name; };int g_ticket 10000…

酒店宾馆民宿预订管理系统(ThinkPHP+uniapp+uView)

便捷高效&#xff0c;轻松管理你的住宿预订&#x1f3e8; 基于ThinkPHPuniappuView开发的多门店民宿酒店预订管理系统&#xff0c;快速部署属于自己民宿酒店的预订小程序&#xff0c;包含预订、退房、WIFI连接、吐槽、周边信息等功能。​​ 一、引言&#xff1a;为何需要民宿…

安卓手机数据快速找回!2个视频恢复大师,助你还原视频

我们的手机成为了储存信息的海洋。但与此同时&#xff0c;也带来了一个不容忽视的问题&#xff1a;一旦手机中的视频资料丢失&#xff0c;我们该如何高效地找回呢&#xff1f;现在很多程序都能够有效地找回手机视频&#xff0c;本文将为您揭示这些视频恢复大师的神奇能力&#…

家用洗地机哪个好?选对洗地机,还你一个清爽的家,快来抄作业!

能够带来高效生活的洗地机已经成为现代家庭清洁的首选。如果你还在犹豫的话&#xff0c;不妨看看这篇文章&#xff0c;让我来带你感受科技清扫的魅力&#xff0c;轻松扫净灰尘污渍&#xff0c;重拾家居整洁。洗地机&#xff0c;不只清洁&#xff0c;更是一种高品质生活态度的选…

【数据结构与算法】对称矩阵,三角矩阵 详解

给出对称矩阵、三角矩阵的节省内存的存贮结构并写出相应的输入、输出算法。 对称矩阵和三角矩阵可以通过特殊的存储结构来节省内存。这种存储结构只存储矩阵的一部分元素&#xff0c;而不是全部元素。 对称矩阵&#xff1a;对于一个n阶对称矩阵&#xff0c;我们只需要存储主对…

大学物理绪论组收集和分析

目录 ​编辑 随机误差的估计 算术平均值的标准偏差 不确定度&#xff08;Uncertainty&#xff09;是测量学中的一个重要概念&#xff0c;用于表示测量结果的可靠程度。它反映了测量值可能偏离真值&#xff08;即被测量的客观真实值&#xff09;的程度。 A类不确定度的计算方…

访问0xdddddddd内存地址引发软件崩溃的实战问题排查

目录 1、问题描述 2、访问空指针或者野指针 3、C程序中常见的异常内存值 4、0xdddddddd内存访问违例问题分析与排查 4.1、初步分析 4.2、CConfMeidaConfigDlg窗口类对象是何时被销毁的&#xff1f; 4.3、为啥会访问到已经释放内存的CConfMeidaConfigDlg类对象&#xff1…

centOS Stream9配置NAT8网络

首先将VMware关机&#xff0c;添加网络适配器 启动虚拟机&#xff0c;查看ens192是否打开连接 安装的图形化需要查看右上角电源处网卡是否连接 最小化安装一般不会出现未连接的状态 使用ip a 查看 配置网卡文件 cd /etc/NetworkManager/system-connections/cd到当前目录下…