SSM实现mysql数据库账号密码加密连接
引言
咱们公司从事的是信息安全涉密应用的一些项目研发一共有分为三步,相比较于一般公司和一般的项目,对于信息安全要求更加严格,领导要求数据量和用户的用户名及密码信息都必需是要密文配置和存储的,这就涉及到jdbc.properties文件中的数据库的用户名和密码也是一样的,需要配置问密文,在连接的时候再加载解密为明文进行数据库的连接操作,以下就是实现过程,一共有分为三步。
一、创建DESUtil类
提供自定义密钥,加密解密的方法。
package com.hzdy.DCAD.common.util; import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;
import java.security.SecureRandom; /**
* Created by Wongy on 2019/8/8.
*/
public class DESUtil {
private static Key key;
//自己的密钥
private static String KEY_STR = "mykey"; static {
try {
KeyGenerator generator = KeyGenerator.getInstance("DES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(KEY_STR.getBytes());
generator.init(secureRandom);
key = generator.generateKey();
generator = null;
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 对字符串进行加密,返回BASE64的加密字符串
*
* @param str
* @return
* @see [类、类#方法、类#成员]
*/
public static String getEncryptString(String str) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
byte[] strBytes = str.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptStrBytes = cipher.doFinal(strBytes);
return base64Encoder.encode(encryptStrBytes);
} catch (Exception e) {
throw new RuntimeException(e);
} } /**
* 对BASE64加密字符串进行解密
*
*/
public static String getDecryptString(String str) {
BASE64Decoder base64Decoder = new BASE64Decoder();
try {
byte[] strBytes = base64Decoder.decodeBuffer(str);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] encryptStrBytes = cipher.doFinal(strBytes);
return new String(encryptStrBytes, "UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
} } public static void main(String[] args) {
String name = "dbuser";
String password = "waction2016";
String encryname = getEncryptString(name);
String encrypassword = getEncryptString(password);
System.out.println("encryname : " + encryname);
System.out.println("encrypassword : " + encrypassword); System.out.println("name : " + getDecryptString(encryname));
System.out.println("password : " + getDecryptString(encrypassword));
}
}
二、 创建EncryptPropertyPlaceholderConfigurer类
建立与配置文件的关联。
package com.hzdy.DCAD.common.util;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
public class EncryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
//属性需与配置文件的KEY保持一直
private String[] encryptPropNames = {"jdbc.username", "jdbc.password"};
@Override
protected String convertProperty(String propertyName, String propertyValue) {
//如果在加密属性名单中发现该属性
if (isEncryptProp(propertyName)) {
String decryptValue = DESUtil.getDecryptString(propertyValue);
System.out.println(decryptValue);
return decryptValue;
} else {
return propertyValue;
}
}
private boolean isEncryptProp(String propertyName) {
for (String encryptName : encryptPropNames) {
if (encryptName.equals(propertyName)) {
return true;
}
}
return false;
}
}
三、 修改配置文件 jdbc.properties
#加密配置之前
#jdbc.driver=com.mysql.jdbc.Driver
#jdbc.user=root
#jdbc.password=root
#jdbc.url=jdbc:mysql://localhost:3306/bookstore #加密配置之后
jdbc.driver=com.mysql.jdbc.Driver
jdbc.user=Ov4j7fKiCzY=
jdbc.password=Ov4j7fKiCzY=
jdbc.url=jdbc:mysql://localhost:3306/bookstore
四、 修改spring-content.xml配置文件
将spring-context中的
<context:property-placeholder location="classpath:.properties" />
修改为
<bean class="com.hzdy.DCAD.common.util.EncryptPropertyPlaceholderConfigurer"p:locations="classpath:*.properties"/>
//注意只能存在一个读取配置文件的bean,否则系统只会读取最前面的
注意:如果发现配置密文的username和password可以加载并解密成功,但是最后连接的时候还是以密文连接并报错,这可能涉及到内存预加载的问题,项目一启动,程序会加密密文的用户名和密码,就算最后解密成功了,最后连接数据库读取的却还是密文,这时候我们可以自己重写连接池的方法,让spring-content.xml加载重写的连接池方法,并在连接的时候再提前进行解密。
package com.thinkgem.jeesite.common.encrypt; import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties; import javax.security.auth.callback.PasswordCallback;
import com.alibaba.druid.util.DruidPasswordCallback; /**
*/
@SuppressWarnings("serial")
public class DruidDataSource extends com.alibaba.druid.pool.DruidDataSource { public PhysicalConnectionInfo createPhysicalConnection() throws SQLException {
String url = this.getUrl();
Properties connectProperties = getConnectProperties(); String user;
if (getUserCallback() != null) {
user = getUserCallback().getName();
} else {
user = getUsername();
}
//DES解密
user = DESUtils.getDecryptString(user);
String password = DESUtils.getDecryptString(getPassword());
PasswordCallback passwordCallback = getPasswordCallback(); if (passwordCallback != null) {
if (passwordCallback instanceof DruidPasswordCallback) {
DruidPasswordCallback druidPasswordCallback = (DruidPasswordCallback) passwordCallback; druidPasswordCallback.setUrl(url);
druidPasswordCallback.setProperties(connectProperties);
} char[] chars = passwordCallback.getPassword();
if (chars != null) {
password = new String(chars);
}
} Properties physicalConnectProperties = new Properties();
if (connectProperties != null) {
physicalConnectProperties.putAll(connectProperties);
} if (user != null && user.length() != 0) {
physicalConnectProperties.put("user", user);
} if (password != null && password.length() != 0) {
physicalConnectProperties.put("password", password);
} Connection conn; long connectStartNanos = System.nanoTime();
long connectedNanos, initedNanos, validatedNanos;
try {
conn = createPhysicalConnection(url, physicalConnectProperties);
connectedNanos = System.nanoTime(); if (conn == null) {
throw new SQLException("connect error, url " + url + ", driverClass " + this.driverClass);
} initPhysicalConnection(conn);
initedNanos = System.nanoTime(); validateConnection(conn);
validatedNanos = System.nanoTime(); setCreateError(null);
} catch (SQLException ex) {
setCreateError(ex);
throw ex;
} catch (RuntimeException ex) {
setCreateError(ex);
throw ex;
} catch (Error ex) {
createErrorCount.incrementAndGet();
throw ex;
} finally {
long nano = System.nanoTime() - connectStartNanos;
createTimespan += nano;
} return new PhysicalConnectionInfo(conn, connectStartNanos, connectedNanos, initedNanos, validatedNanos);
}
}
修改spring-content.xml文件的数据库连接数配置
#修改之前
<!-- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> --> #修改之后
<bean id="dataSource"class="com.thinkgem.jeesite.common.encrypt.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
<property name="driverClassName" value="${jdbc.driver}" />
<!-- 基本属性 url、user、password -->
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" /> </bean>
至此,数据库密文配置连接就完成了!
SSM实现mysql数据库账号密码加密连接的更多相关文章
- MySQL修改账号密码方法大全
前言: 在日常使用数据库的过程中,难免会遇到需要修改账号密码的情景,比如密码太简单需要修改.密码过期需要修改.忘记密码需要修改等.本篇文章将会介绍需要修改密码的场景及修改密码的几种方式. 1.忘记 r ...
- SQL Server数据库账号密码变更后导致vCenter Server无法访问数据库
SQL Server数据库账号密码变更后导致vCenter Server无法访问数据库 1.1状况描述: 若SQL Server数据库的账号(这里以sa为例)密码发生了变更,那么连接数据的客户端vCe ...
- mysql数据库忘记密码时如何修改(二)
第一步:找到mysql数据库的my.ini配置文件,在[mysqld]下面添加一行代码:skip-grant-tables 第二步:运行services.msc进入服务管理界面,重启mysql服务. ...
- 修改MySQL数据库的密码
通过MySQL命令行,可以修改MySQL数据库的密码,下面就为您详细介绍该MySQL命令行,如果您感兴趣的话,不妨一看. 格式:mysql -u用户名 -p旧密码 password 新密码 1.给ro ...
- 【转】mysql数据库中实现内连接、左连接、右连接
[转]mysql数据库中实现内连接.左连接.右连接 内连接:把两个表中数据对应的数据查出来 外连接:以某个表为基础把对应数据查出来 首先创建数据库中的表,数据库代码如下: /* Navicat MyS ...
- 一键强制修改任意Mysql数据库的密码,修改任意环境Mysql数据库。
本文采用我软件里面的内置改密功能,可以一键强制修改Mysql数据库的密码, 在修改过程中,会强制干掉Mysql主程序,修改完成后重新启动Mysql就可以了. 首先讲解如何一键强制修改PHPWAMP自身 ...
- mysql数据库忘记密码时如何修改(一)
方法/步骤 打开mysql.exe和mysqld.exe所在的文件夹,复制路径地址 打开cmd命令提示符,进入上一步mysql.exe所在的文件夹. 输入命令 mysqld --skip-grant ...
- Mysql数据库忘记密码找回方法
Mysql数据库忘记密码找回 a 停止mysql服务 /etc/init.d/mysql stop b 使用--skip-grant-tables启动mysql,忽略授权登录验证 mysqld_saf ...
- mysql数据库的安装和连接测试并给root用户赋密码
一.mysql数据库的安装 Windows下MySQL的配置 以 MySQL 5.1 免安装版为例, 下载 mysql-noinstall-5.1.69-win32.zip ( 官方下载页: http ...
随机推荐
- Docker swarm实战总结
一.简介 Swarm 是 Docker 官方提供的一款集群管理工具,其主要作用是把若干台 Docker 主机抽象为一个整体,并且通过一个入口统一管理这些 Docker 主机上的各种 Docker 资源 ...
- NodeJS4-8静态资源服务器实战_构建cli工具
Cli(command-line interface),中文是 命令行界面,简单来说就是可以通过命令行快速生成自己的项目模板等功能(比较熟悉的是vue-cli脚手架这些),把上述写的包做成Cli工具. ...
- AQS系列(六)- Semaphore的使用及原理
前言 Semaphore也是JUC包中一个用于并发控制的工具类,举个常用场景的例子:有三台电脑五个人,每个人都要用电脑注册一个自己的账户,这时最开始只能同时有三个人操作电脑注册账户,这三个人中有人操作 ...
- iOS WKWebView与JS的交互
参考链接:https://www.jianshu.com/p/524bc8699ac2
- Scrum Meeting - 第七周【Alpha阶段】
每日任务内容: 本次会议为第七次Scrum Meeting会议 本次会议项目经理召开时间为20:00,在北区男生宿舍楼召开,召开时长约10分钟,探讨了本周选课网站编写的后续工作. 小组成员 本周任务 ...
- redlock算法及其问题
背景 redlock算法是为了解决什么问题呢? 在单redis实例实现分布式锁时,可能会出现线程A设置完锁后,master挂掉,slave提升为master,因为异步复制的特性,线程A设置的锁丢失了, ...
- NPM 问题汇总
1. Error: setuid user id does not exist Error: setuid user id does not exist at /usr/local/lib/node_ ...
- GetWindowLong() 函数
Window API函数,可根据nlndex参数的不同获取指定窗口的相关信息,也可用于获取窗口内存中指定偏移的32位度整型值.该值大小在注册窗口类时设定, 函数原型:Long GetWindowLon ...
- reports buileder 触发器的写法
触发器写法: function CF_SHOULD_BACK_TIMEFormula return Number is--其他:取MES工时按工段分别统计产量.投入工时合计:应回报工时=移动数量*[∑ ...
- SpringCloud之Zuul:服务网关
Zuul在Web项目中的使用见上文<SpringBoot中使用Zuul>,下面例子为Zuul在Spring Cloud的使用. 开发工具:IntelliJ IDEA 2019.2.3 一. ...