引言
咱們公司從事的是信息安全涉密應(yīng)用的一些項目研發(fā)一共有分為三步,相比較于一般公司和一般的項目,對于信息安全要求更加嚴格,領(lǐng)導要求數(shù)據(jù)量和用戶的用戶名及密碼信息都必需是要密文配置和存儲的,這就涉及到j(luò)dbc.properties文件中的數(shù)據(jù)庫的用戶名和密碼也是一樣的,需要配置問密文,在連接的時候再加載解密為明文進行數(shù)據(jù)庫的連接操作,以下就是實現(xiàn)過程,一共有分為三步。
一、創(chuàng)建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));
}
}
二、 創(chuàng)建EncryptPropertyPlaceholderConfigurer類
建立與配置文件的關(guān)聯(lián)。
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) {
//如果在加密屬性名單中發(fā)現(xiàn)該屬性
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,否則系統(tǒng)只會讀取最前面的
注意:如果發(fā)現(xiàn)配置密文的username
和password
可以加載并解密成功,但是最后連接的時候還是以密文連接并報錯,這可能涉及到內(nèi)存預加載的問題,項目一啟動,程序會加密密文的用戶名和密碼,就算最后解密成功了,最后連接數(shù)據(jù)庫讀取的卻還是密文,這時候我們可以自己重寫連接池的方法,讓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文件的數(shù)據(jù)庫連接數(shù)配置
#修改之前
!-- 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">
!-- 數(shù)據(jù)源驅(qū)動類可不寫,Druid默認會自動根據(jù)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>
至此,數(shù)據(jù)庫密文配置連接就完成了!
總結(jié)
以上所述是小編給大家介紹的SSM實現(xiàn)mysql數(shù)據(jù)庫賬號密碼密文登錄功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
您可能感興趣的文章:- SQL Server免費版的安裝以及使用SQL Server Management Studio(SSMS)連接數(shù)據(jù)庫的圖文方法
- SQL Server Management Studio(SSMS)復制數(shù)據(jù)庫的方法
- ssm框架上傳圖片保存到本地和數(shù)據(jù)庫示例
- 詳解SSM框架下結(jié)合log4j、slf4j打印日志
- SSM項目中配置LOG4J日志的方法
- SSM整合中的Log4j日志的配置詳情
- SSM框架把日志信息保存到數(shù)據(jù)庫過程詳解