資料來源c3p0連線 密碼加密
阿新 • • 發佈:2019-01-06
(一)背景
最近一個專案的資料來源用的dbcp,dbcp資料來源的連線密碼是加密過得,主要的加密操作是之前同事做的,查了很久,他是修改了dbcp的原始碼,修改了BasicDataSource類裡面的createConnectionFactory()方法,主要是在裡面對加密的密碼進行了解密,再建立連線。
String pwd = reset(password); if (pwd != null) connectionProperties.put("password", pwd); else log("DBCP DataSource configured without a 'password'");
然後,我們只要用他重新打包釋出的dbcp jar包就能用加過密的密碼建立資料庫連線。
現在的情況是,我想換資料來源,但是新的資料來源不想修改原始碼,同時還是使用加密的密碼做資料庫連線,這是為了防止資料庫洩露(雖然說這種方式,是防君子,不防小人)
(二)分析
通過上面的瞭解,可以修改dbcp的原始碼對加密的密碼進行解密,然後建立連線,那麼是不是也可以在不修改原始碼的情況下,攔截原始碼中建立連線時的setPassword()方法,解密後再設定。那麼,應該攔截哪個方法呢?或者說繼承
(三)測試
1.配置檔案修改
<bean id="dataSourceProperties" class="com.dooioo.datasource.PropertiesEncryptFactoryBean"> <property name="properties"> <props> <prop key="user" >${${env}.boms.jdbc.username}</prop> <prop key="password" >${${env}.boms.jdbc.password}</prop> </props> </property> </bean> <!--組織架構資料來源--> <bean id="bomsDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="jdbcUrl" value="${${env}.boms.jdbc.url}"/> <property name="driverClass" value="${${env}.boms.jdbc.driver}"/> <property name="properties" ref="dataSourceProperties"/> <!-- <property name="username" value="${${env}.boms.jdbc.username}"/> <property name="password" value="${${env}.boms.jdbc.password}"/> --> <!-- <property name="initialSize" value="5"/> <property name="maxActive" value="50"/> <property name="maxIdle" value="2"/> <property name="minIdle" value="1"/> <property name="defaultAutoCommit" value="true"/> --> </bean>
2.PropertiesEncryptFactoryBean(加密類)
public class PropertiesEncryptFactoryBean implements FactoryBean{ private Properties properties; public Object getObject() throws Exception { return getProperties(); } public Class getObjectType() { return java.util.Properties.class; } public boolean isSingleton() { return true; } public Properties getProperties() { return properties; } public void setProperties(Properties inProperties) { this.properties = inProperties; String originalUsername = properties.getProperty("user"); String originalPassword = properties.getProperty("password"); //if (originalUsername != null){ // String newUsername = deEncryptUsername(originalUsername); properties.put("user", originalUsername); // } if (originalPassword != null){ String newPassword; try { newPassword = reset(originalPassword); properties.put("password", newPassword); } catch (InvalidKeyException | SQLNestedException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private String deEncryptUsername(String originalUsername){ return deEncryptString(originalUsername); } private String deEncryptPassword(String originalPassword){ return deEncryptString(originalPassword); } //簡單加密 private String deEncryptString(String originalString){ StringBuilder newString = new StringBuilder(); for (int i = 0; i < originalString.length(); i++) { char eachChar= originalString.charAt(i); char newChar = (char)(eachChar + i); newString.append(newChar); } return newString.toString(); } private String reset(String secret) throws SQLNestedException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { byte decode[]; byte kbytes[] = "TjE5MGQ5".getBytes(); SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish"); BigInteger n = new BigInteger(secret, 16); byte encoding[] = n.toByteArray(); Cipher cipher = Cipher.getInstance("Blowfish"); cipher.init(2, key); decode = cipher.doFinal(encoding); return new String(decode); } }
這裡使用的加密解密演算法是Cipher,因為我們需要的加密解密的密碼是一樣的,所以需要使用對稱的加密解密演算法。
測試下來,這樣是可以的。
(四)總結
這種方式是主要是利用了spring載入順序,因為在載入c3p0載入之前先對配置檔案中的密碼進行相應的解密,並且注入到屬性password中,這樣在建立c3p0連線的時候,用的密碼就是明文密碼了。
這裡的資料來源安全機制感覺還不是很靠譜,下面需要試驗更改原始碼。