在Springboot中创建自定义Jasypt PropertySource [英] Creating a custom Jasypt PropertySource in Springboot

查看:108
本文介绍了在Springboot中创建自定义Jasypt PropertySource的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Spring Boot创建一个访问数据库的简单Web应用程序.我通过在application.properties中设置spring.datasource.*属性来利用DataSource的自动配置功能.一切都很棒,而且非常快-伟大的工作人员@ Spring!

I'm using Spring Boot to create a simple web application which accesses a database. I'm taking advantage of the autoconfiguration functionality for the DataSource by setting up spring.datasource.* properties in application.properties. That all works brilliantly and was very quick - great work guys @ Spring!

我公司的政策是不应使用明文密码.因此,我需要对sping.datasource.password进行加密.经过一番挖掘后,我决定创建一个org.springframework.boot.env.PropertySourceLoader实现,该实现将创建一个jasypt org.jasypt.spring31.properties.EncryptablePropertiesPropertySource,如下所示:

My companys policy is that there should be no clear text passwords. Therefore I need to have the sping.datasource.password encrypted. 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:

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;
    }
}

然后我将其包装在它自己的jar中,并带有一个META-INF/spring.factories文件,如下所示:

I then packaged this in it's own jar with a META-INF/spring.factories file as follows:

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

当使用mvn spring-boot:run从maven运行时,这非常理想.当我使用java -jar my-app.war作为独立战争运行它时,会发生问题.该应用程序仍然加载,但是当我尝试连接到数据库时由于密码值仍然被加密而失败.添加日志记录显示EncryptedPropertySourceLoader从未加载.

This works perfectly when run from maven using mvn spring-boot:run. The problem occurs when I run it as a standalone war using 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.

对我来说,这听起来像是类路径问题.在maven下运行时,jar的加载顺序很严格,但是一旦进入了tomcat的tomcat,就无话可说,我的自定义jar应该在Spring Boot之前加载.

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.

我尝试将以下内容添加到pom.xml中,以确保保留了classpth,但它似乎没有任何作用.

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.

<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.

更新:

向前迈进:我已经设法通过使EncryptedPropertySourceLoader类实现org.springframework.core.PriorityOrdered接口并从getOrder()返回HIGHEST_PRECEDENCE来解决此问题.现在,这已解决了不使用PropertySourceLoader的问题.但是,现在尝试解密属性时会引发以下错误:

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(). This has now fixed the issue of the PropertySourceLoader not being used. 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)

同样,从mvn spring-boot:run运行时不会发生,但从可执行war文件运行时会发生.两种方案都使用相同的JVM(jdk1.6.0_35). Google/Stackoverflow上的结果表明这是Java安全策略的一个问题,但是由于它在从Maven运行时确实有效,我认为我可以对此予以保留.可能是包装问题...

Again this doesn't happen when running from mvn spring-boot:run but does happen when running from the executable war file. Both scenarios use the same 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. Possibly a packaging issue...

推荐答案

这里有两个问题.

1)EncryptedPropertySourceLoader的加载需要比标准PropertiesPropertySourceLoader的加载高.这可以通过实现如下的PriorityOrder接口来实现:

1) The EncryptedPropertySourceLoader needs to be loaded higher than then standard PropertiesPropertySourceLoader. This can be achieved by implementing the PriorityOrder interface as follows:

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;
    }
}

META-INF/spring.factories加载org.springframework.boot.env.PropertySourceLoaderorg.springframework.core.io.support.SpringFactoriesLoader类使用org.springframework.core.OrderComparator对结果进行排序.意味着该类应首先返回,并将负责为* .proerpties文件提供PropertySourceLoader实现.

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. Meaning that this class should be returned first and will be given the responsibility of providinging the PropertySourceLoader implementation for *.proerpties files.

2)第二个问题是可执行JAR/WAR的类加载问题,这似乎是由Windows上的Spring Boot版本1.1.2.RELEASE中的错误引起的.降级到1.1.1.RELEASE版本或1.1.3.RELEASE版本解决了在maven之外运行时类和属性文件未加载的各种问题.

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. 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.

这篇关于在Springboot中创建自定义Jasypt PropertySource的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆