Spring-使用加密的属性文件02

简介: Spring-使用加密的属性文件02

概述


对于不敏感的属性信息,以明文形式出现在属性文件中是合适的,但是如果属性信息是数据库用户名和密码等敏感信息,一般希望以密文的方式保存。


这就要求对应用程序配置文件的某些属性进行加密,让Spring容器在读取属性文件后,在内存中对属性进行解密,然后将解密后的属性值赋给目标对象。


我们来看下 PropertyPlaceholderConfigurer的继承关系

20170807063302874.jpg

PropertyResourceConfigurer类中有几个方法


20170807063415397.jpg


实例

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster


20170807105018061.jpg

DES加密解密工具类


信息的加密分为对称和非对称两种方式, 前者表示加密后的信息可以解密为原值,而后者则不能根据加密后的信息还原为原值。


MD5属于非对称加密, DES属于对称加密。

先用DES对属性值进行加密,在读取到属性值时,在用DES进行解密。

DES加密解密工具类

package com.xgj.ioc.propertyplacehoderEncryption;
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class DESUtils {
    private static Key key;
    // 指定DES加密解密用的密钥
    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 (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 
     * 
     * @Title: getEncryptString
     * 
     * @Description: 对字符串进行加密,返回BASE64编码的加密字符串
     * 
     * @param str
     * @return
     * 
     * @return: String
     */
    public static String getEncryptString(String str) {
        BASE64Encoder base64en = new BASE64Encoder();
        try {
            byte[] strBytes = str.getBytes("UTF8");
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encryptStrBytes = cipher.doFinal(strBytes);
            return base64en.encode(encryptStrBytes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 
     * 
     * @Title: getDecryptString
     * 
     * @Description:对BASE64编码的加密字符串进行解密,返回解密后的字符串
     * 
     * @param str
     * @return
     * 
     * @return: String
     */
    public static String getDecryptString(String str) {
        BASE64Decoder base64De = new BASE64Decoder();
        try {
            byte[] strBytes = base64De.decodeBuffer(str);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decryptStrBytes = cipher.doFinal(strBytes);
            return new String(decryptStrBytes, "UTF8");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 
     * 
     * @Title: main
     * 
     * @Description: 测试方法
     * 
     * @param args
     * @throws Exception
     * 
     * @return: void
     */
    public static void main(String[] args) throws Exception {
        System.out.println(getEncryptString("cc"));
        System.out.println(getEncryptString("zsmart2017"));
        System.out.println(getDecryptString("SkR6wWI9iws="));
        System.out.println(getDecryptString("lSR/mscM1NE3sM98QFjAdw=="));
    }
}


使用密文版的属性文件

  1. 运行 DESUtils, 得到 用户名和密码的加密字符串
  2. 修改jdbc.properties


jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@172.25.246.11:1521:xgj
jdbc.username=SkR6wWI9iws=
jdbc.password=lSR/mscM1NE3sM98QFjAdw==


PropertyPlaceholderConfigurer 本身不支持密文版的属性文件,不过我们可以扩展该类,重写 String convertProperty(String propertyName, String propertyValue)方法


package com.xgj.ioc.propertyplacehoderEncryption;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
/**
 * 
 * 
 * @ClassName: EncryptPropertyPlaceholderConfigurer
 * 
 * @Description: 继承PropertyPlaceholderConfigurer,重写convertProperty方法,对属性进行解密
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年8月6日 下午11:01:23
 */
public class EncryptPropertyPlaceholderConfigurer extends
        PropertyPlaceholderConfigurer {
    // 对应jdbc.properties中的key
    private String[] encryptPropNames = { "jdbc.username", "jdbc.password" };
    @Override
    protected String convertProperty(String propertyName, String propertyValue) {
        if (isEncryptProp(propertyName)) {
            String decryptValue = DESUtils.getDecryptString(propertyValue);
            System.out.println("解密后的字符串:" + decryptValue);
            return decryptValue;
        } else {
            return propertyValue;
        }
    }
    /**
     * 判断是否是加密的属性
     * 
     * @param propertyName
     * @return
     */
    private boolean isEncryptProp(String propertyName) {
        for (String encryptPropName : encryptPropNames) {
            if (encryptPropName.equals(propertyName)) {
                return true;
            }
        }
        return false;
    }
}


EncryptPropertyPlaceholderConfigurer使用DESUtils中的方法解密加密后的字符串。


修改配置文件,引用自定义的EncryptPropertyPlaceholderConfigurer

<!-- 引入JDBC属性文件  加密-->
    <bean  class="com.xgj.ioc.propertyplacehoderEncryption.EncryptPropertyPlaceholderConfigurer"
        p:location="classpath:spring/jdbc.properties"
        p:fileEncoding="utf-8"/> 

使用自定义的属性加载器后,就无法使用context:property-placeholder属性加载配置文件了,必须使用传统的方式引用加密版的属性文件,如上

完整的配置文件:

<?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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->
    <context:component-scan base-package="com.xgj.ioc.propertyplacehoderEncryption"/>
    <!-- 引入JDBC属性文件  加密-->
    <bean  class="com.xgj.ioc.propertyplacehoderEncryption.EncryptPropertyPlaceholderConfigurer"
        p:location="classpath:spring/jdbc.properties"
        p:fileEncoding="utf-8"/> 
    <!-- 通过属性名引用属性值 -->     
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"
        p:driverClassName="${jdbc.driverClassName}"
        p:url="${jdbc.url}"
        p:username="${jdbc.username}"
        p:password="${jdbc.password}"/>
    <!-- 配置Jdbc模板  -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
        p:dataSource-ref="dataSource" />
</beans>

测试类

package com.xgj.ioc.propertyplacehoderEncryption;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class PropertyPlaceHoderEncryptionTest {
    private final static String MATCH_COUNT_SQL = " SELECT count(*) FROM temp_user  "
            + " WHERE user_name =? and password=? ";
    private JdbcTemplate jdbcTemplate;
    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    /**
     * 
     * 
     * @Title: getMatchCount
     * 
     * @Description: 根据用户名和密码判断用户是否存在
     * 
     * @param username
     * @param password
     * 
     * @return: int
     */
    public int getMatchCount(String username, String password) {
        return jdbcTemplate.queryForObject(MATCH_COUNT_SQL, new Object[] {
                username, password }, Integer.class);
    }
    /**
     * 
     * 
     * @Title: main
     * 
     * @Description: 测试
     * 
     * @param args
     * 
     * @return: void
     */
    public static void main(String[] args) {
        // 加载Spring配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/ioc/propertyplacehoderEncryption/beans.xml");
        // 获取通过注解标注的Bean
        PropertyPlaceHoderEncryptionTest propertyplacehoderEncryption = ctx
                .getBean("propertyPlaceHoderEncryptionTest",
                        PropertyPlaceHoderEncryptionTest.class);
        // 调用方法
        int count = propertyplacehoderEncryption.getMatchCount("xgj", "123456");
        System.out.println("匹配的用户数量:" + count);
    }
}


测试结果


20170807113905360.jpg


相关文章
|
4月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
1057 10
|
9月前
|
Java 测试技术 微服务
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
本课主要讲解Spring Boot项目中的属性配置方法。在实际开发中,测试与生产环境的配置往往不同,因此不应将配置信息硬编码在代码中,而应使用配置文件管理,如`application.yml`。例如,在微服务架构下,可通过配置文件设置调用其他服务的地址(如订单服务端口8002),并利用`@Value`注解在代码中读取这些配置值。这种方式使项目更灵活,便于后续修改和维护。
178 0
|
5月前
|
人工智能 安全 Java
Spring Boot yml 配置敏感信息加密
本文介绍了如何在 Spring Boot 项目中使用 Jasypt 实现配置文件加密,包含添加依赖、配置密钥、生成加密值、在配置中使用加密值及验证步骤,并提供了注意事项,确保敏感信息的安全管理。
1205 1
|
6月前
|
存储 Java 数据安全/隐私保护
Java技术栈揭秘:Base64加密和解密文件的实战案例
以上就是我们今天关于Java实现Base64编码和解码的实战案例介绍。希望能对你有所帮助。还有更多知识等待你去探索和学习,让我们一同努力,继续前行!
491 5
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
368 2
|
9月前
|
存储 安全 数据安全/隐私保护
Hyper V文件复制安全:加密与访问控制
在Hyper-V环境中,确保文件复制的安全性至关重要。主要措施包括:启用数据加密、使用HTTPS协议和磁盘加密技术(如BitLocker)保护数据传输和存储;通过身份验证、权限管理和审核日志控制访问;定期更新补丁、实施网络隔离及制定备份恢复策略。这些多层次的安全措施共同防止未经授权的访问和数据泄露,保障数据安全。
Hyper V文件复制安全:加密与访问控制
|
9月前
|
编解码 安全 Java
如何在Spring Boot中实现数据加密
本文介绍了如何在Spring Boot中实现数据加密。首先阐述了数据加密的重要性与应用场景,接着讲解了对称加密和非对称加密的原理及区别。通过添加依赖、配置加密算法、编写加密工具类等步骤,展示了具体实现方法,并在业务代码中应用加密技术保护敏感数据。希望对开发者有所帮助。
722 7
|
9月前
|
Java 数据库 微服务
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——指定项目配置文件
在实际项目中,开发环境和生产环境的配置往往不同。为简化配置切换,可通过创建 `application-dev.yml` 和 `application-pro.yml` 分别管理开发与生产环境配置,如设置不同端口(8001/8002)。在 `application.yml` 中使用 `spring.profiles.active` 指定加载的配置文件,实现环境快速切换。本节还介绍了通过配置类读取参数的方法,适用于微服务场景,提升代码可维护性。课程源码可从 [Gitee](https://gitee.com/eson15/springboot_study) 下载。
383 0
|
9月前
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
在微服务架构中,随着业务复杂度增加,项目可能需要调用多个微服务。为避免使用`@Value`注解逐一引入配置的繁琐,可通过定义配置类(如`MicroServiceUrl`)并结合`@ConfigurationProperties`注解实现批量管理。此方法需在配置文件中设置微服务地址(如订单、用户、购物车服务),并通过`@Component`将配置类纳入Spring容器。最后,在Controller中通过`@Resource`注入配置类即可便捷使用,提升代码可维护性。
186 0
|
12月前
|
Java Spring
【Spring配置】创建yml文件和properties或yml文件没有绿叶
本文主要针对,一个项目中怎么创建yml和properties两种不同文件,进行配置,和启动类没有绿叶标识进行解决。