spring读取加密属性

在开发和设计过程中,通常需要对一些配置数据进行加密,如数据库的连接方式等,在读取到加密数据后,我们必须解密后才能使用。

以下是来自书籍《Spring 3.x 企业应用开发实战》示例,可做参考!
一、编写加密代码DESUtil.java
/**
 * DESUtil.java
 * cn.com.songjy
 * Function: TODO 
 *
 *   version    date      author
 * ──────────────────────────────────
 *   	1.0	 2013-9-25    songjy
 *
 * Copyright (c) 2013, TNT All Rights Reserved.
 */

package cn.com.songjy;

import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * ClassName:DESUtil
 * 
 * @author songjy
 * @version 1.0
 * @since v1.0
 * @Date 2013-9-25 下午4:19:48
 */

public class DESUtil {

	private static Log log = LogFactory.getLog(DESUtil.class);

	public static void main(String[] args) {

		if (null != args)
			if (1 <= args.length)
				for (String src : args)
					log.info(src + ":" + encrypt(src));

	}

	/* 1、指定DES加密解密所用的密钥 */
	private static Key key;
	private static String KEY_STR = "myKey";

	static {
		try {
			KeyGenerator generator = KeyGenerator.getInstance("DES");
			generator.init(new SecureRandom(KEY_STR.getBytes()));
			key = generator.generateKey();
			generator = null;
		} catch (NoSuchAlgorithmException e) {
			log.error(e.getMessage(), e);
		}
	}

	/* 2、对字符串进行DES加密,返回BASE64编码的加密字符串 */
	public static String encrypt(String src/* 明文 */) {
		BASE64Encoder base64en = new BASE64Encoder();
		try {
			byte[] src_byte = src.getBytes("UTF-8");
			Cipher cipher = Cipher.getInstance("DES");
			cipher.init(Cipher.ENCRYPT_MODE, key);
			byte[] final_byte = cipher.doFinal(src_byte);
			return base64en.encode(final_byte);
		} /*
		 * catch (UnsupportedEncodingException e) { log.info(e.getMessage(), e);
		 * } catch (NoSuchAlgorithmException e) { log.info(e.getMessage(), e); }
		 * catch (NoSuchPaddingException e) { log.info(e.getMessage(), e); }
		 */catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}

	/* 3、对BASE64编码的加密字符串进行解密,返回解密后的字符串 */
	public static String decrypt(String src/* 密文 */) {
		BASE64Decoder base64de = new BASE64Decoder();
		try {
			byte[] src_byte = base64de.decodeBuffer(src);
			Cipher cipher = Cipher.getInstance("DES");
			cipher.init(Cipher.DECRYPT_MODE, key);
			byte[] decrypt_byte = cipher.doFinal(src_byte);
			return new String(decrypt_byte, "UTF-8");
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}
}


二、继承PropertyPlaceholderConfigurer类并实现接口convertProperty
/**
 * EncryptPropertyPlaceholderConfigurer.java
 * cn.com.songjy
 * Function: TODO 
 *
 *   version    date      author
 * ──────────────────────────────────
 *   	1.0	 2013-9-25    songjy
 *
 * Copyright (c) 2013, TNT All Rights Reserved.
*/

package cn.com.songjy;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

/**
 * ClassName:EncryptPropertyPlaceholderConfigurer
 *
 * @author   songjy
 * @version  1.0
 * @since    v1.0
 * @Date	 2013-9-25	下午4:22:13
 */

public class EncryptPropertyPlaceholderConfigurer extends
		PropertyPlaceholderConfigurer {

	private Log log = LogFactory.getLog(EncryptPropertyPlaceholderConfigurer.class);
	
	/**
	 * (non-Javadoc)
	 * @see org.springframework.beans.factory.config.PropertyResourceConfigurer#convertProperty(java.lang.String, java.lang.String)
	 */
	@Override
	protected String convertProperty(String propertyName, String propertyValue) {
		
		if(encryptPropNames.contains(propertyName))//属性propertyName的值加密了,需要解密
			return DESUtil.decrypt(propertyValue);
		
		return super.convertProperty(propertyName, propertyValue);
		
	}
	
	private List<String> encryptPropNames;//保存加密的属性字段

	public List<String> getEncryptPropNames() {
		return encryptPropNames;
	}

	public void setEncryptPropNames(List<String> encryptPropNames) {
		for (String string : encryptPropNames) {
			log.info("属性"+string+"的值已加密");
		}
		this.encryptPropNames = encryptPropNames;
	}
}


三、编写属性文件保存类,测试时用
/**
 * MyConfig.java
 * cn.com.songjy
 * Function: TODO 
 *
 *   version    date      author
 * ──────────────────────────────────
 *   	1.0	 2013-9-26    songjy
 *
 * Copyright (c) 2013, TNT All Rights Reserved.
*/

package cn.com.songjy;

/**
 * ClassName:MyConfig
 *
 * @author   songjy
 * @version  1.0
 * @since    v1.0
 * @Date	 2013-9-26	上午9:31:56
 */

public class MyConfig {

	private String username;
	private String password;
	
	private String username1;
	private String password1;
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getUsername1() {
		return username1;
	}
	public void setUsername1(String username1) {
		this.username1 = username1;
	}
	public String getPassword1() {
		return password1;
	}
	public void setPassword1(String password1) {
		this.password1 = password1;
	}
	
}


四、创建属性文件
song.properties
song1.properties
其中
song.properties保存的是密文,如下:
username=Pa3HE99AWOg=
password=QAHlVoUc49w=

song.properties保存的是明文,如下:
username1=songjy
password1=123456

五、编写Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

	<bean class="cn.com.songjy.EncryptPropertyPlaceholderConfigurer">
		<property name="encryptPropNames">
			<list>
				<value>username</value>
				<value>password</value>
			</list>
		</property>
		<property name="locations">
			<list>
				<value>classpath:cn/com/songjy/song.properties</value>
				<value>classpath:cn/com/songjy/song1.properties</value>
			</list>
		</property>
	</bean>

	<bean id="my" class="cn.com.songjy.MyConfig">
		<property name="username" value="${username}"/>
		<property name="password" value="${password}"/>
		<property name="username1" value="${username1}"/>
		<property name="password1" value="${password1}"/>
	</bean>
	
</beans>

六、测试类编写
/**
 * Test.java
 * cn.com.songjy
 * Function: TODO 
 *
 *   version    date      author
 * ──────────────────────────────────
 *   	1.0	 2013-9-26    songjy
 *
 * Copyright (c) 2013, TNT All Rights Reserved.
*/

package cn.com.songjy;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * ClassName:Test
 *
 * @author   songjy
 * @version  1.0
 * @since    v1.0
 * @Date	 2013-9-26	上午9:35:31
 */

public class Test {

	/**
	 * @method main
	 * @param args
	 * @since v1.0
	 */

	public static void main(String[] args) {

		ApplicationContext ac = new ClassPathXmlApplicationContext("cn/com/songjy/beans.xml");
		
		//MyConfig my = (MyConfig) ac.getBean("my");
		MyConfig my = ac.getBean(MyConfig.class);
		
		System.out.println(my.getUsername().equals(my.getUsername1()));
		System.out.println(my.getPassword().equals(my.getPassword1()));

	}

}




public void encrypt_MD5() {
		String 明文密码 = "123456";
		try {
			java.security.MessageDigest md = java.security.MessageDigest
					.getInstance("MD5");
			md.update(明文密码.getBytes());
			byte b[] = md.digest();
			int i;
			StringBuffer buf = new StringBuffer();
			for (int offset = 0; offset < b.length; offset++) {
				i = b[offset];
				if (i < 0)
					i += 256;
				if (i < 16)
					buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			System.out.println("密文: " + buf.toString());// 32位的加密
			System.out.println("密文: " + buf.toString().substring(8, 24));// 16位的加密
		} catch (java.security.NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}

MD5加密效果如下:



DES对称加密的实现及其源代码

用 Java 解密 C# 加密的数据(DES)

Java文件加密-spring属性文件加密

Spring获取Bean的几种方式
MD5,salt,SHA,PBKDF2加密

备注:本次示例使用的Spring版本是:spring-core-3.2.4.RELEASE

猜你喜欢

转载自songjianyong.iteye.com/blog/1947441