整体流程
①在在配置文件applicatiooncontext中设置自定义的配置文件解析的属性,
<bean id="appPropertyConfigurer" class="com.fjep.common.PropertyConfigurer" abstract="false" lazy-init="default" autowire="default"> <property name="locations"> <list> <value>classpath:/config/database.properties</value> </list> </property> <property name="decodePropertyNames"> <list> <value>database.dev.username</value> <value>database.dev.password</value> </list> </property> </bean>
②PropertyConfigurer工具类中会判断decodePropertyNames的value值是否与PropertyNames中的名称一致,如果一致,就会进行解密操作
③使用MessageDigestCodingUtil工具类进行加密和解密,加密是先进行base64加密,在进行16位加密;解密反过来,先解16位,在进行64位的解密。
1.Base64的加密类
package com.fjep.utils; /** *说明:64位加密算法 */ public class Base64 { private static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray(); private static byte codes[]; public Base64() { } public static byte[] decode(char data[]) { int tempLen = data.length; for (int ix = 0; ix < data.length; ix++) { if (data[ix] > '\377' || codes[data[ix]] < 0) { tempLen--; } } int len = (tempLen / 4) * 3; if (tempLen % 4 == 3) { len += 2; } if (tempLen % 4 == 2) { len++; } byte out[] = new byte[len]; int shift = 0; int accum = 0; int index = 0; for (int ix = 0; ix < data.length; ix++) { int value = data[ix] <= '\377' ? ( (int) (codes[data[ix]])) : -1; if (value >= 0) { accum <<= 6; shift += 6; accum |= value; if (shift >= 8) { shift -= 8; out[index++] = (byte) (accum >> shift & 0xff); } } } if (index != out.length) { throw new Error("Miscalculated data length (wrote " + index + " instead of " + out.length + ")"); } else { return out; } } public static char[] encode(byte data[]) { char out[] = new char[ ( (data.length + 2) / 3) * 4]; int i = 0; for (int index = 0; i < data.length; index += 4) { boolean quad = false; boolean trip = false; int val = 0xff & data[i]; val <<= 8; if (i + 1 < data.length) { val |= 0xff & data[i + 1]; trip = true; } val <<= 8; if (i + 2 < data.length) { val |= 0xff & data[i + 2]; quad = true; } out[index + 3] = alphabet[quad ? val & 0x3f : 64]; val >>= 6; out[index + 2] = alphabet[trip ? val & 0x3f : 64]; val >>= 6; out[index + 1] = alphabet[val & 0x3f]; val >>= 6; out[index] = alphabet[val & 0x3f]; i += 3; } return out; } static { codes = new byte[256]; for (int i = 0; i < 256; i++) { codes[i] = -1; } for (int i = 65; i <= 90; i++) { codes[i] = (byte) (i - 65); } for (int i = 97; i <= 122; i++) { codes[i] = (byte) ( (26 + i) - 97); } for (int i = 48; i <= 57; i++) { codes[i] = (byte) ( (52 + i) - 48); } codes[43] = 62; codes[47] = 63; } public static void main(String[] args) { try { String encode = new String(Base64.encode("ioffice".getBytes())); System.out.println(encode); System.out.println(new String(Base64.decode("5a6d706c634441774d413d3d".toCharArray()))); } catch (Exception e) { e.printStackTrace(); } } }
2.具体加密解密的工具类MessageDigestCodingUtil
package com.fjep.utils; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; /** *说明:进行数值摘要的加密和解密处理 */ public class MessageDigestCodingUtil { /** * *摘要:加密操作 *@说明:先进行64位的加密 再继续16进制的加密 *@param encode *@return */ public static String encode(String encode) { encode=new String(Base64.encode(encode.getBytes())); encode=new String(Hex.encodeHex(encode.getBytes())); return encode; } /** * *摘要:解密操作 *@说明:先进行16进制的解密,再进行64位的解密 *@param decode *@return */ public static String decode(String decode) { try { decode=new String(Hex.decodeHex(decode.toCharArray())); decode=new String(Base64.decode(decode.toCharArray())); } catch (DecoderException e) { e.printStackTrace(); } return decode; } public static void main(String[] args) { //String str=MessageDigestCodingUtil.encode("jdbc:oracle:thin:@10.188.80.98:1521:dev"); //System.out.println("encrypt="+MessageDigestCodingUtil.encode("root")); System.out.println("encrypt1="+MessageDigestCodingUtil.decode("5a6d706c634639335a57493d")); // System.out.println("encrypt="+MessageDigestCodingUtil.decode("5a6d706c634441774d413d3d")); } }
3.对配置文件操作的类PropertyConfigurer
package com.fjep.common; import java.io.IOException; import java.util.Enumeration; import java.util.List; import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import org.springframework.util.ObjectUtils; import com.fjep.utils.MessageDigestCodingUtil; /** *说明:对.properties文件进行解析操作 */ public class PropertyConfigurer extends PropertyPlaceholderConfigurer { private static final Log log=LogFactory.getLog(PropertyConfigurer.class); /** * 需要进行解密的属性名称 decodePropertyNames * <list> * <value>zbs</value> * <value>zbs2</value> * </list> */ private List<String> decodePropertyNames; private Properties springPropertiesDatas=null; @SuppressWarnings("unchecked") @Override protected void convertProperties(Properties props) { Enumeration propertyNames = props.propertyNames(); while (propertyNames.hasMoreElements()) { String propertyName = (String) propertyNames.nextElement(); String propertyValue = props.getProperty(propertyName); String convertedValue=null; if(this.decodePropertyNames!=null&&decodePropertyNames.size()>0) { if(this.decodePropertyNames.contains(propertyName)) { convertedValue=MessageDigestCodingUtil.decode(propertyValue); }else { convertedValue = convertPropertyValue(propertyValue); } }else convertedValue = convertPropertyValue(propertyValue); if (!ObjectUtils.nullSafeEquals(propertyValue, convertedValue)) { props.setProperty(propertyName, convertedValue); } } } public List<String> getDecodePropertyNames() { return decodePropertyNames; } public void setDecodePropertyNames(List<String> decodePropertyNames) { this.decodePropertyNames = decodePropertyNames; } public String getPropertyValue(String key) { if(springPropertiesDatas==null) { try { this.springPropertiesDatas=super.mergeProperties(); } catch (IOException e) { log.equals(e); } } String value=this.springPropertiesDatas.get(key).toString(); if(this.decodePropertyNames.contains(key)) { value=MessageDigestCodingUtil.decode(value); } return value; } }
4.在applicationContext.xml文件添加如下设置,
<!-- 自定义的属性解析文件 --> <bean id="appPropertyConfigurer" class="com.fjep.common.PropertyConfigurer" abstract="false" lazy-init="default" autowire="default"> <property name="locations"> <list> <value>classpath:/config/database.properties</value> </list> </property> <property name="decodePropertyNames"> <list> <value>database.dev.username</value> <value>database.dev.password</value> </list> </property> </bean>
5.datasouce.property
#本地数据库连接
database.dev.password=636d397664413d3d
database.dev.url=jdbc:mysql://localhost:3306/selected
database.dev.username=636d397664413d3d
database.driver=com.mysql.jdbc.Driver
hibernate.show_sql=false
#初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。
database.initialPoolSize=2
#连接池中保留的最小连接数
database.minPoolSize=2
#连接池中保留的最大连接数。
database.maxPoolSize=8
#最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0
database.maxIdleTime=60
#每30分钟检查所有连接池中的空闲连接。Default: 0
database.idleConnectionTestPeriod=1800
#org.gjt.mm.mysql.Driver
#com.mysql.jdbc.Driver
database.checkoutTimeout=60000
#org.gjt.mm.mysql.Driver
#com.mysql.jdbc.Driver
database.timeBetweenEvictionRunsMillis=60000
database.minEvictableIdleTimeMillis=300000
database.validationQuery=SELECT 'x' from dual
database.testWhileIdle=true
database.testOnBorrow=false
database.testOnReturn=false
database.filters=stat
database.poolPreparedStatements=true
database.maxOpenPreparedStatements=50