SpringMVC 项目数据库用户名密码加密解密

SpringMVC 项目数据库用户名密码加密解密

文章目录

  • SpringMVC 项目数据库用户名密码加密解密
    • 前言
    • 原有spring mvc配置
    • 加密解密步骤
      • 步骤1:选取加密算法DesUtil
      • 步骤二:配置PropertyPlaceholderConfigurer
      • 步骤三:数据库配置文件替换需要加密明文信息
      • 步骤四:修改spring mvc配置文件

前言

在使用springMVC开发web项目中,为了数据安全,数据库的用户名,密码一般都是配置在.properties文件中,相关密码尽可能进行密文保存,防止信息泄露。

本项目中,使用了druid数据库连接池,连接池的相关配置会存在在单独的文件。

原有spring mvc配置

然后在通过.xml配置文件引入.properties的变量,例如

比如:dbconfig.properties

###########测试环境############
url=jdbc:mysql://xxx:3306/db?useUnicode=true&characterEncoding=utf-8;autoReconnect=true
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver
filters=stat
maxActive=20
initialSize=1
maxWait=60000
minIdle=10
maxIdle=15
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
validationQuery=SELECT 'x'
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
maxOpenPreparedStatements=20
removeAbandoned=true
removeAbandonedTimeout=1800
logAbandoned=true

原先的配置扫面通过以下配置

<context:property-placeholder location="classpath:dbconfig.properties,classpath:app.properties" file-encoding="utf-8"/>

druid的数据源配置如下:

<bean id="pooledDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">  
	    
	    <property name="url" value="${url}" />
	    <property name="username" value="${username}" />
	    <property name="password" value="${password}" />
		<property name="driverClassName" value="${driverClassName}" />
		<property name="filters" value="${filters}" />
		
		<property name="maxActive" value="${maxActive}" />
		
		<property name="initialSize" value="${initialSize}" />
		
		<property name="minIdle" value="${minIdle}" />
		
		<property name="maxWait" value="${maxWait}" />
		
		<property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
		
		<property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
		<property name="validationQuery" value="${validationQuery}" />
		<property name="testWhileIdle" value="${testWhileIdle}" />
		<property name="testOnBorrow" value="${testOnBorrow}" />
		<property name="testOnReturn" value="${testOnReturn}" />
		<property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" />
		
		<property name="removeAbandoned" value="${removeAbandoned}" />
		
		<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
		
		<property name="logAbandoned" value="${logAbandoned}" />  
	bean>

以上的配置需要对数据库username和password进行加密,加密算法选DES。

加密解密步骤

步骤1:选取加密算法DesUtil

package com.csii.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;

public class DesUtil {
    private static Key key;
    private static String KEY_STR = "test-key";

    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();
        System.out.println(key);
        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加密字符串进行解密
     * <功能详细描述>
     *
     * @param str
     * @return
     * @see [类、类#方法、类#成员]
     */
    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 String getDecryptStringByKey(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 = "root";
        String password = "123456";
        String encryname = getEncryptString(name);
        String encrypassword = getEncryptString(password);
        System.out.println(encryname);
        System.out.println(encrypassword);

        System.out.println(getDecryptString(encryname));
        System.out.println(getDecryptString(encrypassword));
    }
}

测试main方法输出:
com.sun.crypto.provider.DESKey@186a1
com.sun.crypto.provider.DESKey@186a1
kzaWDiA6UD8=
AfVZ4X447eg=
root
123456

步骤二:配置PropertyPlaceholderConfigurer

提醒:因测试使用System.out.println 这种不严谨的打印日志方式,实际开发请注意规范。
当前想要更安全的加密方式,可以使用AES等其他加密也行。

PropertiesUtil配置文件:

package com.csii.util;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.util.StringUtils;

public final class PropertiesUtil extends PropertyPlaceholderConfigurer {
    private Logger logger = Logger.getLogger(PropertiesUtil.class);
    private static Map<String, String> ctxPropertiesMap; // 用于存放perperties中的数据
    private List<String> decryptProperties; // 用于存放需要解密的key

    @Override
    protected void loadProperties(Properties props) throws IOException {
        super.loadProperties(props);
        ctxPropertiesMap = new HashMap<String, String>();
        System.out.println("要加载的文件:" + props.keySet());
        for (Object key : props.keySet()) {
            String keyStr = key.toString();
            String value = props.getProperty(keyStr);
            if (decryptProperties != null && decryptProperties.contains(keyStr)) {
                value = DesUtil.getDecryptString(value); // 解密
                props.setProperty(keyStr, value); // 设置解密后的明文数据
                System.out.println("解密后的内容:" + value);
            }
            ctxPropertiesMap.put(keyStr, value);
        }
    }

    /**
     * @param decryptProperties
     */
    public void setDecryptProperties(List<String> decryptProperties) {
        this.decryptProperties = decryptProperties;
    }

    /**
     * Get a value based on key , if key does not exist , null is returned
     *
     * @param key
     * @return
     */
    public static String getString(String key) {
        try {
            return ctxPropertiesMap.get(key);
        } catch (MissingResourceException e) {
            return null;
        }
    }

    /**
     * 根据key获取值
     *
     * @param key
     * @return
     */
    public static int getInt(String key) {
        return Integer.parseInt(ctxPropertiesMap.get(key));
    }

    /**
     * 根据key获取值
     *
     * @param key
     * @param defaultValue
     * @return
     */
    public static int getInt(String key, int defaultValue) {
        String value = ctxPropertiesMap.get(key);
        if (StringUtils.isEmpty(value)) {
            return defaultValue;
        }
        return Integer.parseInt(value);
    }

    /**
     * 根据key获取值
     *
     * @param key
     * @param defaultValue
     * @return
     */
    public static boolean getBoolean(String key, boolean defaultValue) {
        String value = ctxPropertiesMap.get(key);
        if (StringUtils.isEmpty(value)) {
            return defaultValue;
        }
        return new Boolean(value);
    }

}

步骤三:数据库配置文件替换需要加密明文信息

在这里插入代码片
```json
###########测试环境############
url=jdbc:mysql://xxx:3306/db?useUnicode=true&characterEncoding=utf-8;autoReconnect=true
username=kzaWDiA6UD8=
password=AfVZ4X447eg=
driverClassName=com.mysql.jdbc.Driver
filters=stat
maxActive=20
initialSize=1
maxWait=60000
minIdle=10
maxIdle=15
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
validationQuery=SELECT 'x'
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
maxOpenPreparedStatements=20
removeAbandoned=true
removeAbandonedTimeout=1800
logAbandoned=true

步骤四:修改spring mvc配置文件



	<bean class="com.csii.util.PropertiesUtil">

         <property name="locations">
             <list>
				 <value>classpath:app.propertiesvalue>
				 <value>classpath:dbconfig.propertiesvalue>
             list>
         property>

         <property name="decryptProperties">
             <array>

				 <value>usernamevalue>
				 <value>passwordvalue>
             array>
         property>
     bean>

配置完成后重新启动spring mvc服务,测试密文信息,是否解密生效。

你可能感兴趣的:(spring,mvc)