如何在 Spring 的属性文件中以加密形式存储密码

Posted

技术标签:

【中文标题】如何在 Spring 的属性文件中以加密形式存储密码【英文标题】:How to store password as encrypted in properties file in Spring 【发布时间】:2012-07-23 15:12:21 【问题描述】:

我是 Spring 框架的新手,我正在使用 Spring 框架来管理我的数据库连接等等。应用程序从属性文件中读取我的数据库连接参数。我需要的是将我的连接密码加密存储在属性文件中。 这是我的数据源 xml 文件

    <?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:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>file:$DBConfigFile</value>
        </property>
    </bean>

    <bean id="myDataSource"   class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="$jdbc.driverClassName" />
        <property name="jdbcUrl" value="$jdbc.url" />
        <property name="user" value="$jdbc.username" />
        <property name="password" value="$jdbc.password" />
        <property name="initialPoolSize"><value>3</value></property>
        <property name="minPoolSize"><value>3</value></property>
        <property name="maxPoolSize"><value>50</value></property>
        <property name="idleConnectionTestPeriod"><value>200</value></property>
        <property name="acquireIncrement"><value>1</value></property>
        <property name="maxStatements"><value>0</value></property>
        <property name="numHelperThreads"><value>3</value></property>
    </bean>

</beans>

我想将加密的密码写入属性文件,我想知道 Spring 是否可以使用算法自动解密它。是否可以通过配置。 提前谢谢你。

【问题讨论】:

【参考方案1】:

据我所知,Spring 不支持此功能,但其他一些项目可能会有所帮助:

Jasypt library 提供对加密应用程序配置的支持(并且还与 Spring 集成)。查看详情:http://www.jasypt.org/encrypting-configuration.html

OWASP Project 提供了带有DefaultEncryptedProperties 和ReferenceEncryptedProperties 实现的EncryptedProperties 接口,这些实现可以在您的应用程序中使用。另见:https://www.owasp.org/index.php/How_to_encrypt_a_properties_file

【讨论】:

【参考方案2】:

我使用的是 spring 4 和 jasypt 1.9。 Jasypt 文档没有提供对 spring 4 的明确支持。我也找不到名为 EncryptablePropertyPlaceholderConfigurer 的类和 org.jasypt:jasypt:1.9.2 依赖项。

我编写了一个简单的静态加密实用程序 java 类(它使用 jasypt API)。

public class EncryptionUtil 
    static PooledPBEStringEncryptor encryptor = null;
    static 
        encryptor = new PooledPBEStringEncryptor();
        encryptor.setPoolSize(4); 
        //  There are various approaches to pull this configuration via system level properties. 
        encryptor.setPassword("parashar");
        encryptor.setAlgorithm("PBEWITHMD5ANDDES");
    

    public static String encrypt(String input) 
        return encryptor.encrypt(input);
    

    public static String decrypt(String encryptedMessage) 
        return encryptor.decrypt(encryptedMessage);
    


我使用此实用程序来加密我打算保留在我的属性文件中的密码。

然后我简单地使用 spring EL 将属性解密回我的 spring 配置 xml。

<property name="password" value="#T(amit.parashar.EncryptionUtil).decrypt('$db.password')" />

编辑: 回答如何隐藏加密密码:

Use system args while bringing up your java process. 

例如: java -Dwhatismyencpawd="parashar"

并像使用它

encryptor.setPassword(java.lang.System.getProperty("whatismyencpawd"));

这样只有应用管理员知道密码。这种方式密码将作为 ps 命令的一部分在 UNIX 机器上可见。

或者您也可以配置和读取操作系统级别的环境变量。

【讨论】:

我不明白,现在我将如何保护“parashar”,因为如果有人检查代码并且他/她可以正确解密?【参考方案3】:

这没有任何意义,因为如果 Spring 可以解密它,那么其他人也可以。这种加密不会有任何区别,它不会保护任何东西。它只会带来危险的东西——虚假的保护感。

也许您可以使用其他数据库身份验证方式,例如MS SQL 服务器允许使用 Windows 安全而不是密码验证。 Postgres 也是如此(它通过用户帐户或使用 SSL 证书提供访问权限)。

【讨论】:

你是对的,但我提到了 Spring 的私有算法,而不是公共算法。谢谢你的回答,我去搜索一下ssl认证。 @tace 用于安全的私有算法是矛盾的。 en.wikipedia.org/wiki/Security_through_obscurity 。因此,正确的一种方法是使用操作系统保护(Windows NTLM、Unix pam 等),它可以提供一些保护。 通过属性中的加密凭据,您可以将它们与需要它们的服务一起保持版本控制(显然不与私钥一起),并在部署服务时自动部署。唯一需要在部署管道之外维护的是用于解密属性的私钥,这应该比在服务的正常生命周期之外维护整个配置更不容易出错。 @SebastianGanslandt 如果您能够在系统中安全地维护一个私钥文件,那么您为什么还需要它呢?它有什么不同?我认为这只会让整个事情变得更加困难——你需要维护密钥,引入一个安全的程序来更改密码,并添加这个特殊的魔法 Spring 配置。吻。在我们的项目中,我们有一个外部“security.properties”文件,它定义了所有敏感信息并且永远不会离开部署目标服务器。 这实际上是我在徘徊到加密属性之前考虑的解决方案,当内置弹簧支持的想法仍然存在时,这似乎更优雅。【参考方案4】:

可以使用spring cloud config提供的encryption and decryption

【讨论】:

好的,但是怎么做?该页面似乎描述了如何使用 Spring Cloud 客户端和服务器从配置服务器接收解密的属性。但是我对维护一个服务只是为了处理解密属性没有兴趣,那么如何将属性的解密机制拉入正常的 Spring 应用程序上下文中呢?【参考方案5】:

你可以编写一个 bean 来解密你的密码,然后将 bean 注入到任何需要密码的地方

【讨论】:

有没有办法在 pom.xml 中注入?

以上是关于如何在 Spring 的属性文件中以加密形式存储密码的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Spring框架加密文档中的所有MongoDB字段

Spring MVC - 如何在 Rest Controller 中以 JSON 形式返回简单字符串

如何在 Spring Boot Rest API 中以 XML 形式返回对象列表

如何解除文件夹加密

在 iOS 中以流的形式读取加密的 PDF

如何在 Spring 中以编程方式解析属性占位符