`
tang9140
  • 浏览: 35133 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

spring_jdbc数据库配置项中用户名及密码密文处理类(防黑客入侵用)

 
阅读更多

原始配置

spring结合mysql,一般是单独出配置文件jdbc.properties,

配置如下

driverClassName=com.mysql.jdbc.Driver
db.mysql.url=jdbc:mysql://127.0.0.1:3306/tq?autoReconnect=true&useUnicode=true&characterEncoding=utf8
db.mysql.username=test
db.mysql.password=123456

配置spring-jdbc.xml,使其加载该配置项。示例如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
		http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-3.0.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
	default-autowire="byName">

	<context:annotation-config />
	<!-- 扫描组件,完成自动装配 -->
	<context:component-scan base-package="com.tq.app.epg.dao" />

	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:jdbc.properties</value>
			</list>
		</property>
	</bean>
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close" lazy-init="true" depends-on="propertyConfigurer">
		<property name="driverClass" value="${driverClassName}" />
		<property name="jdbcUrl" value="${db.mysql.url}" />
		<property name="user" value="${db.mysql.username}" />
		<property name="password" value="${db.mysql.password}" />
		<property name="autoCommitOnClose" value="true" />
		<property name="minPoolSize" value="5" />
		<property name="maxPoolSize" value="80" />
		<property name="maxIdleTime" value="1800" />
		<property name="maxStatements" value="100" />
		<property name="acquireIncrement" value="5" />
		<property name="idleConnectionTestPeriod" value="6000" />
		<property name="testConnectionOnCheckout" value="true" />
		<property name="checkoutTimeout" value="10000" />
	</bean>
	
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
        	<property name="dataSource" ref="dataSource" /> 
    	</bean>
    
</beans>

按上面进行配置,由于数据库连接、账号、密码是明文,存在泄露风险。可以在配置文件中存密文,在spring读取该配置文件时,进行解密。

改进配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
		http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-3.0.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
	default-autowire="byName">

	<context:annotation-config />
	<!-- 扫描组件,完成自动装配 -->
	<context:component-scan base-package="com.tq.app.epg.dao" />

	<bean id="propertyConfigurer"
		class="com.tq.app.epg.utils.config.GvtvPropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:jdbc.properties</value>
			</list>
		</property>
	</bean>
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close" lazy-init="true" depends-on="propertyConfigurer">
		<property name="driverClass" value="${driverClassName}" />
		<property name="jdbcUrl" value="${db.mysql.url}" />
		<property name="user" value="${db.mysql.username}" />
		<property name="password" value="${db.mysql.password}" />
		<property name="autoCommitOnClose" value="true" />
		<property name="minPoolSize" value="5" />
		<property name="maxPoolSize" value="80" />
		<property name="maxIdleTime" value="1800" />
		<property name="maxStatements" value="100" />
		<property name="acquireIncrement" value="5" />
		<property name="idleConnectionTestPeriod" value="6000" />
		<property name="testConnectionOnCheckout" value="true" />
		<property name="checkoutTimeout" value="10000" />
	</bean>
	
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
        	<property name="dataSource" ref="dataSource" /> 
    	</bean>
</beans>

注意上面类GvtvPropertyPlaceholderConfigurer,该类的实现如下:

package com.tq.app.epg.utils.config;

import java.util.Enumeration;
import java.util.Properties;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

public class GvtvPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
        
        AESHelper aesHelper = new AESHelper();
        Enumeration<?> keys = props.propertyNames();
        while (keys.hasMoreElements()) {
            String key = (String)keys.nextElement();
            String value = props.getProperty(key);
            if (key.endsWith(".encryption") && null != value) {
                props.remove(key);
                key = key.substring(0, key.length() - 11);
                value = aesHelper.decrypt(value.trim());
                props.setProperty(key, value);
            }
            System.setProperty(key, value);
        }
        
        super.processProperties(beanFactoryToProcess, props);
    }
}

相应的jdbc.properties变为

driverClassName=com.mysql.jdbc.Driver
db.mysql.url.encryption=XXXXXXXXXXXXXXXXXXXXXXX
db.mysql.username.encryption=D12450E55E370A310C1AAAB5189BB42A
db.mysql.password.encryption=ADC6327D7DB1D55623B70B48614A331B

另附AESHelper类:

package com.tq.app.epg.utils.config;

import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * <一句话功能简述>
 */
public class AESHelper {
    Cipher ecipher;
    
    Cipher dcipher;
    
    /**
     * Input a string that will be md5 hashed to create the key.
     * 
     * @return void, cipher initialized
     */
    public AESHelper() {
        try {
            SecretKeySpec skey = new SecretKeySpec("9f265d42ab3c66d8f50a3a2e793a30c2".getBytes(), "AES");
            this.setupCrypto(skey);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public AESHelper(String key) {
        SecretKeySpec skey = new SecretKeySpec(getMD5(key), "AES");
        this.setupCrypto(skey);
    }
    
    private void setupCrypto(SecretKey key) {
        // Create an 8-byte initialization vector
        byte[] iv = new byte[]
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
        
        AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
        try {
            ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            
            // CBC requires an initialization vector
            ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
            dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // Buffer used to transport the bytes from one stream to another
    // byte[] buf = new byte[1024];
    
    public void encrypt(InputStream in, OutputStream out) {
        byte[] buf = new byte[1024];
        try {
            // Bytes written to out will be encrypted
            out = new CipherOutputStream(out, ecipher);
            
            // Read in the cleartext bytes and write to out to encrypt
            int numRead = 0;
            while ((numRead = in.read(buf)) >= 0) {
                out.write(buf, 0, numRead);
            }
            out.close();
        }
        catch (java.io.IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Input is a string to encrypt.
     * 
     * @return a Hex string of the byte array
     */
    public String encrypt(String plaintext) {
        try {
            byte[] ciphertext = ecipher.doFinal(plaintext.getBytes("UTF-8"));
            return byteToHex(ciphertext);
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        
    }
    
    public void decrypt(InputStream in, OutputStream out) {
        try {
            byte[] buf = new byte[1024];
            // Bytes read from in will be decrypted
            in = new CipherInputStream(in, dcipher);
            
            // Read in the decrypted bytes and write the cleartext to out
            int numRead = 0;
            while ((numRead = in.read(buf)) >= 0) {
                out.write(buf, 0, numRead);
            }
            out.close();
        }
        catch (java.io.IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Input encrypted String represented in HEX
     * 
     * @return a string decrypted in plain text
     */
    public String decrypt(String hexCipherText) {
        try {
            String plaintext = new String(dcipher.doFinal(hexToByte(hexCipherText)), "UTF-8");
            return plaintext;
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public String decrypt(byte[] ciphertext) {
        try {
            String plaintext = new String(dcipher.doFinal(ciphertext), "UTF-8");
            return plaintext;
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    private static byte[] getMD5(String input) {
        try {
            byte[] bytesOfMessage = input.getBytes("UTF-8");
            MessageDigest md = MessageDigest.getInstance("MD5");
            return md.digest(bytesOfMessage);
        }
        catch (Exception e) {
            return null;
        }
    }
    
    static final String HEXES = "0123456789ABCDEF";
    
    public static String byteToHex(byte[] raw) {
        if (raw == null) {
            return null;
        }
        final StringBuilder hex = new StringBuilder(2 * raw.length);
        for (final byte b : raw) {
            hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
        }
        return hex.toString();
    }
    
    public static byte[] hexToByte(String hexString) {
        int len = hexString.length();
        byte[] ba = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            ba[i / 2] =
                (byte)((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
        }
        return ba;
    }
    
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

分享到:
评论

相关推荐

    Spring中jdbc.properties属性文件进行密文处理

    这是一个简单的案例用来实现Spring中jdbc.properties属性文件进行密文处理,代码中的学生实体自己根据需要在数据库中进行创建

    druid配置数据库连接使用密文密码

    ### Druid配置数据库连接使用密文密码 在现代软件开发中,安全性成为了不可或缺的一部分。数据库作为存储敏感信息的核心组件,其安全防护尤为重要。其中,数据库连接的密码管理是基础且关键的一环。传统的做法是在...

    proxool连接池用户名密码加密

    Proxool的加密功能允许我们在配置中使用加密的用户名和密码,确保即使配置文件被泄露,攻击者也无法直接获取到明文的数据库凭据。这增强了系统的安全性,降低了数据泄露的风险。 在提供的压缩包文件中,可能包含了...

    denglu.rar_MFC登陆界面_mfc用户名密码_mfc的登陆界面

    本文将深入探讨如何使用Microsoft Foundation Class (MFC)库在VC6环境下设计一个简单的登录界面,包括用户名和密码的输入验证。 MFC是微软为Windows应用程序开发提供的一套类库,它基于C++构建,为开发者提供了创建...

    tomcat_连接池数据库密码加密解密方法

    然而,当数据库的用户名和密码直接硬编码在配置文件(如Tomcat的`server.xml`)中时,这些敏感信息容易被泄露,从而构成安全隐患。因此,实现数据库密码的加密存储和解密读取成为了一项必要的技术实践。 #### 重要...

    Springboot项目对数据库用户名密码实现加密过程解析

    本文详细介绍了如何在Springboot项目中实现数据库用户名密码的加密过程,包括使用jasypt库对密码进行加密、配置加密后的密码密文到Spring Boot配置文件中,以及设置加密的秘钥环境变量。希望本文能够对大家的学习和...

    cas server 5.3.9 整合数据库验证用户信息,使用security密码验证方式

    在`cas-server-support-jdbc`模块中,你可以配置`PasswordEncoder`来处理密码的加密和解密。 4. **创建认证处理器**:使用Spring Security的`UserDetailsService`接口创建一个自定义实现,这个接口用于从数据库中...

    SpringBoot(七)SpringBoot整合Druid实现数据库密码加密.pdf

    在实际的生产环境中,数据库的安全性非常重要,尤其是数据库连接信息中的用户名和密码。为了防止这些敏感信息被泄露,通常需要采取措施来保护这些信息。本文将详细介绍如何在Spring Boot项目中整合Druid连接池,并...

    用户登陆界面设计,包括用户名及密码的输入

    - 用户凭证存储:用户的用户名和密码通常存储在数据库中,但为了安全,密码应该进行哈希加盐处理,而不是明文存储。 - 数据库查询:在用户提交登录信息后,系统会将输入与数据库中的记录进行匹配。 - SQL注入防护...

    MFC 登录用户名和密码设计

    在本文中,我们将深入探讨如何在MFC(Microsoft Foundation Class)框架下设计一个登录系统,该系统要求用户输入用户名和密码。MFC是Microsoft提供的一种C++类库,用于简化Windows应用程序开发。对于初学者来说,...

    java字符串-用户名和密码-加密解密

    在Java中,对字符串进行加密和解密是一种常见的安全措施,特别是在处理敏感数据如用户名和密码时。通过加密技术可以保护这些数据免受未经授权的访问。 #### 1.2 使用场景 - **邮箱加密**:用于保护用户邮件地址不被...

    HTML基于Web的数据库加密与密文检索系统源码.zip

    HTML基于Web的数据库加密与密文检索系统源码HTML基于Web的数据库加密与密文检索系统源码HTML基于Web的数据库加密与密文检索系统源码HTML基于Web的数据库加密与密文检索系统源码HTML基于Web的数据库加密与密文检索...

    C++用户名+密码登录程序.rar

    在C++编程环境中,开发一个用户名和密码登录程序是一项基础但重要的任务,它涉及到用户身份验证和安全性。本文将深入探讨这个主题,并基于提供的“C++用户名+密码登录程序”来解析关键知识点。 首先,我们要了解C++...

    高分项目基于AES密文检索系统源码+项目说明+数据库.zip

    高分项目基于AES密文检索系统源码+项目说明+数据库.zip 高分项目基于AES密文检索系统源码+项目说明+数据库.zip 高分项目基于AES密文检索系统源码+项目说明+数据库.zip 高分项目基于AES密文检索系统源码+项目说明+...

    VC++获取WinNT_Win2k当前用户名和密码.zip

    在Windows操作系统中,尤其是WinNT和Win2K环境下,开发者经常需要获取当前登录用户的用户名和密码信息,这对于系统权限管理、安全验证等场景至关重要。在C++编程中,可以通过使用Windows API来实现这一功能。本资源...

    nacos2.0.4版本使用RSA算法加密之后的源码,可以直接使用。

    下载nacos源码之后进行代码编写,修改了前端用户名和密码加密传输,后端使用RSA算法将收到的信息进行解码判断。内容包含源代码、打包之后的zip文件以及tar.gz文件,可以直接使用。 适用人群:项目使用nacos作为注册...

    spring中的数据源配置信息加密方案

    在Spring框架中,数据源(DataSource)是连接数据库的关键组件,通常包含敏感信息,如数据库URL、用户名和密码。为了确保这些信息的安全,我们需要对它们进行加密。本篇将详细介绍如何在Spring应用中实现数据源配置...

    思科密文密码破解

    思科密文密码破解 根据加密后的密码推算出明文密码

    本地用户名密码DES加密保存

    4. **密文存储**:将加密后的用户名和密码以密文形式存储在本地数据库或文件中。为了增加安全性,可以考虑使用哈希函数(如SHA系列)对用户名进行处理后再存储,因为用户名通常不需要解密,只需用于验证。 5. **...

Global site tag (gtag.js) - Google Analytics