引言
咱们公司从事的是信息安全涉密应用的一些项目研发一共有分为三步,相比较于一般公司和一般的项目,对于信息安全要求更加严格,领导要求数据量和用户的用户名及密码信息都必需是要密文配置和存储的,这就涉及到jdbc.properties文件中的数据库的用户名和密码也是一样的,需要配置问密文,在连接的时候再加载解密为明文进行数据库的连接操作,以下就是实现过程,一共有分为三步。
一、创建DESUtil类
提供自定义密钥,加密解密的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
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类
建立与配置文件的关联。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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
1
2
3
4
5
6
7
8
9
10
|
#加密配置之前
#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配置文件
1
2
3
4
5
|
将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
加载重写的连接池方法,并在连接的时候再提前进行解密。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
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文件的数据库连接数配置
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#修改之前
<! -- <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数据库账号密码密文登录功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
原文链接:https://www.cnblogs.com/zhaosq/archive/2019/08/09/11321157.html