简体   繁体   English

在Springboot中创建自定义Jasypt PropertySource

[英]Creating a custom Jasypt PropertySource in Springboot

I'm using Spring Boot to create a simple web application which accesses a database. 我正在使用Spring Boot创建一个访问数据库的简单Web应用程序。 I'm taking advantage of the autoconfiguration functionality for the DataSource by setting up spring.datasource.* properties in application.properties . 我通过在application.properties设置spring.datasource.*属性来利用DataSource的自动配置功能。 That all works brilliantly and was very quick - great work guys @ Spring! 这一切都很出色,非常快 - 很棒的工作人员@Spring!

My companys policy is that there should be no clear text passwords. 我公司的政策是不应该有明文密码。 Therefore I need to have the sping.datasource.password encrypted. 因此,我需要加密sping.datasource.password After a bit of digging around I decided to create a org.springframework.boot.env.PropertySourceLoader implementation which creates a jasypt org.jasypt.spring31.properties.EncryptablePropertiesPropertySource as follows: 经过一番挖掘后,我决定创建一个org.springframework.boot.env.PropertySourceLoader实现,它创建了一个jasypt org.jasypt.spring31.properties.EncryptablePropertiesPropertySource ,如下所示:

public class EncryptedPropertySourceLoader implements PropertySourceLoader
{
    private final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();

    public EncryptedPropertySourceLoader()
    {
        //TODO: this could be taken from an environment variable
        this.encryptor.setPassword("password"); 
    }

    @Override
    public String[] getFileExtensions()
    {
        return new String[]{"properties"};
    }

    @Override
    public PropertySource<?> load(final String name, final Resource resource, final String profile) throws IOException
    {
        if (profile == null)
        {
            final Properties props = PropertiesLoaderUtils.loadProperties(resource);

            if (!props.isEmpty())
            {
                return new EncryptablePropertiesPropertySource(name, props, this.encryptor);
            }
        }

        return null;
    }
}

I then packaged this in it's own jar with a META-INF/spring.factories file as follows: 然后我将它打包在它自己的jar中,带有META-INF/spring.factories文件,如下所示:

org.springframework.boot.env.PropertySourceLoader=com.mycompany.spring.boot.env.EncryptedPropertySourceLoader

This works perfectly when run from maven using mvn spring-boot:run . 当使用mvn spring-boot:run从maven运行时,这非常有效。 The problem occurs when I run it as a standalone war using java -jar my-app.war . 当我使用java -jar my-app.war将其作为独立的战争运行时,会出现问题。 The application still loads but fails when I try to connect to the database as the password value is still encrypted. 当我尝试连接到数据库时,应用程序仍然加载但失败,因为密码值仍然是加密的。 Adding logging reveals that the EncryptedPropertySourceLoader is never loaded. 添加日志记录显示从未加载EncryptedPropertySourceLoader

To me this sounds like a classpath issue. 对我来说这听起来像是一个类路径问题。 When run under maven the jar loading order is strict but once under the embebed tomcat there is nothing to say that my custom jar should be loaded before Spring Boot. 在maven下运行时,jar加载顺序是严格的,但是一旦在嵌入的tomcat下,没有什么可说的,我的自定义jar应该在Spring Boot之前加载。

I've tried adding the following to my pom.xml to ensure the classpth is preserved but it doesn't seem to have had any effect. 我已经尝试将以下内容添加到我的pom.xml中以确保保留classpth但它似乎没有任何影响。

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                    <archive>
                        <manifest>
                            <mainClass>${start-class}</mainClass>
                            <addClasspath>true</addClasspath>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Does anyone have any ideas? 有没有人有任何想法? Thanks in advance. 提前致谢。

UPDATE: 更新:

A step forward: I've managed to fix this by having the EncryptedPropertySourceLoader class implement org.springframework.core.PriorityOrdered interface and returning HIGHEST_PRECEDENCE from getOrder() . 向前迈出的一步:我设法通过让EncryptedPropertySourceLoader类实现org.springframework.core.PriorityOrdered接口并从getOrder()返回HIGHEST_PRECEDENCE来解决这个问题。 This has now fixed the issue of the PropertySourceLoader not being used. 这已经解决了未使用PropertySourceLoader的问题。 However it's now throwing the following error when it tries to decrypt the properties: 但是,当它尝试解密属性时,它现在抛出以下错误:

org.jasypt.exceptions.EncryptionInitializationException: java.security.NoSuchAlgorithmException: PBEWithMD5AndDES SecretKeyFactory not available
    at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.initialize(StandardPBEByteEncryptor.java:716)
    at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.initialize(StandardPBEStringEncryptor.java:553)
    at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:705)
    at org.jasypt.properties.PropertyValueEncryptionUtils.decrypt(PropertyValueEncryptionUtils.java:72)
    at org.jasypt.properties.EncryptableProperties.decode(EncryptableProperties.java:230)
    at org.jasypt.properties.EncryptableProperties.get(EncryptableProperties.java:209)
    at org.springframework.core.env.MapPropertySource.getProperty(MapPropertySource.java:36)
    at org.springframework.boot.env.EnumerableCompositePropertySource.getProperty(EnumerableCompositePropertySource.java:49)
    at org.springframework.boot.context.config.ConfigFileApplicationListener$ConfigurationPropertySources.getProperty(ConfigFileApplicationListener.java:490)

Again this doesn't happen when running from mvn spring-boot:run but does happen when running from the executable war file. mvn spring-boot:run时,这不会发生,但是从可执行war文件运行时确实发生了。 Both scenarios use the same JVM (jdk1.6.0_35). 两种方案都使用相同的JVM(jdk1.6.0_35)。 Results on Google/Stackoverflow suggest this is an issue with the java security policy but as it does work when run from maven I think I can discount that. Google / Stackoverflow上的结果表明这是java安全策略的一个问题,但是当它从maven运行时确实有效,我想我可以打折。 Possibly a packaging issue... 可能是包装问题......

There are two issues here. 这里有两个问题。

1) The EncryptedPropertySourceLoader needs to be loaded higher than then standard PropertiesPropertySourceLoader. 1)需要加载EncryptedPropertySourceLoader高于标准的PropertiesPropertySourceLoader。 This can be achieved by implementing the PriorityOrder interface as follows: 这可以通过实现PriorityOrder接口来实现,如下所示:

public class EncryptedPropertySourceLoader implements PropertySourceLoader, PriorityOrdered
{
    private final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();

    public EncryptedPropertySourceLoader()
    {
        this.encryptor.setPassword("password"); //TODO: this could be taken from an environment variable
    }

    @Override
    public String[] getFileExtensions()
    {
        return new String[]{"properties"};
    }

    @Override
    public PropertySource<?> load(final String name, final Resource resource, final String profile) throws IOException
    {
        if (profile == null)
        {
            //load the properties
            final Properties props = PropertiesLoaderUtils.loadProperties(resource);

            if (!props.isEmpty())
            {
                //create the encryptable properties property source
                return new EncryptablePropertiesPropertySource(name, props, this.encryptor);
            }
        }

        return null;
    }

    @Override
    public int getOrder()
    {
        return HIGHEST_PRECEDENCE;
    }
}

The org.springframework.core.io.support.SpringFactoriesLoader class which loads the org.springframework.boot.env.PropertySourceLoader from the META-INF/spring.factories orders the results using org.springframework.core.OrderComparator . META-INF/spring.factories加载org.springframework.boot.env.PropertySourceLoaderorg.springframework.core.io.support.SpringFactoriesLoader类使用org.springframework.core.OrderComparator对结果进行META-INF/spring.factories Meaning that this class should be returned first and will be given the responsibility of providinging the PropertySourceLoader implementation for *.proerpties files. 这意味着应该首先返回此类,并且将负责为* .proerpties文件提供PropertySourceLoader实现。

2) The second is a class loading issue with the executable JAR/WAR which seems to be caused by a bug in version 1.1.2.RELEASE of Spring Boot on Windows. 2)第二个是可执行JAR / WAR的类加载问题,这似乎是由Windows上的Spring Boot 1.1.2.RELEASE版本中的错误引起的。 Dropping to version 1.1.1.RELEASE or to version 1.1.3.RELEASE solves the various issues with classes and proerpties file not being loaded when run outside of maven. 删除版本1.1.1.RELEASE或版本1.1.3.RELEASE解决了在maven外部运行时没有加载类和proerpties文件的各种问题。

You could give this a try: jasypt-spring-boot It basically wraps all PropertySource present in the Environment with an encryptable version. 你可以尝试一下: jasypt-spring-boot它基本上用环境包装加密版本中存在的所有PropertySource。 The 2 things you gotta do once you import the library (adding the dependency if you use maven) is to annotate your @Configuration class with @EnableEncryptableProperties, and to configure the encryption algorithm and password through properties. 导入库后要做的两件事(如果使用maven则添加依赖关系)是使用@EnableEncryptableProperties注释@Configuration类,并通过属性配置加密算法和密码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 有没有一种方法可以使Jasypt在Springboot中具有自定义加密 - Is there a way to make jasypt to have custom encryption in Springboot Springboot中的Custom PropertySource阻止加载某些属性 - Custom PropertySource in Springboot prevents some properties from loading 在SpringBoot的@PropertySource中指定value属性 - Specifying value attribute in @PropertySource in SpringBoot 从 PropertySource Springboot 迭代属性 - Iterate over properties from a PropertySource Springboot Springboot错误读取@PropertySource上的环境变量 - Springboot error reading environment variable on @PropertySource Kotlin/SpringBoot 中@PropertySource 中的@Value 注入困难 - Difficulty in @Value Injection in @PropertySource in Kotlin/SpringBoot 在Springboot mongodb中创建一个自定义查询(使用crudRepository) - creating a custom query in Springboot mongodb(using crudRepository) 使用--spring.config.location = / etc / foo /的Springboot @PropertySource - Springboot @PropertySource with --spring.config.location=/etc/foo/ Springboot中使用@ConfigurationProperties和@PropertySource时如何将属性序列化为对象? - In Springboot, how to serialize properties into objects when using @ConfigurationProperties and @PropertySource? 使用通配符使用@PropertySource(SpringBoot)读取多个属性文件 - Reading multiple properties files with @PropertySource (SpringBoot)using wildcard character
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM