当前位置: 首页 > 知识库问答 >
问题:

在Springboot中创建自定义Jasypt PropertySource

酆鸿哲
2023-03-14

我正在使用Spring Boot创建一个访问数据库的简单web应用程序。通过在application.properties中设置spring.DataSource.*属性,我利用了DataSource的自动配置功能。这一切都很出色,而且非常快--伟大的工作伙计们@Spring!

我公司的政策是不应该有明文密码。因此,我需要对sping.datasource.password进行加密。经过一番深入研究,我决定创建一个org.springframework.boot.env.propertysourceLoader实现,该实现创建一个jasyptorg.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;
    }
}

然后,我用META-INF/spring.factorys文件将其打包到它自己的jar中,如下所示:

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

当在maven中使用MVN spring-boot:run运行时,这种方法可以很好地工作。当我使用java-jar my-app.war将它作为独立的war运行时,就会出现这个问题。应用程序仍然加载,但当我试图连接到数据库时失败,因为密码值仍然是加密的。添加日志显示EncryptedPropertySourceLoader从未加载。

对我来说,这听起来像是一个类路径问题。在maven下运行时,jar加载顺序是严格的,但是一旦在被盗用的tomcat下,就没有什么可以说的了,我的自定义jar应该在Spring Boot之前加载。

我尝试将以下内容添加到pom.xml中,以确保保留类,但似乎没有任何效果。

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

有人有什么想法吗?提前谢了。

更新:

向前一步:我设法解决了这个问题,方法是让EncryptedPropertySourceLoader类实现org.springframework.core.priorityordered接口,并从getOrder()返回highest_preasence。这已经解决了PropertySourceLoader未被使用的问题。但是,当它试图解密属性时,现在抛出以下错误:

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上运行时确实有效,我想我可以忽略这一点。可能是包装问题...

共有1个答案

左丘繁
2023-03-14

这里有两个问题。

1)EncryptedPropertySourceLoader的加载需要高于标准PropertiesPropertySourceLoader。这可以通过实现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;
    }
}

org.springframework.core.io.support.SpringFactoriesLoader类从Meta-INF/spring.Factorys中加载org.springframework.boot.env.propertysourceLoader使用org.springframework.core.orderComparator对结果进行排序。这意味着这个类应该首先返回,并负责为*.Proerpties文件提供PropertySourceLoader实现。

2)第二个是可执行JAR/WAR的类加载问题,这似乎是由Windows上Spring Boot的版本1.1.2中的bug引起的。转到版本1.1.1.Release或版本1.1.3.Release解决了在Maven之外运行时无法加载类和proerpties文件的各种问题。

 类似资料:
  • 问题内容: 有没有一种方法可以JButton用您自己的按钮图形而不是仅在按钮内部创建图像? 如果没有,是否还有另一种方法可以JButton在Java中创建自定义? 问题答案: 当我第一次学习Java时,我们不得不制造Yahtzee,我认为创建自定义的Swing组件和容器会很酷,而不仅仅是在一个组件上绘制所有内容JPanel。Swing当然,扩展组件的好处是能够添加对键盘快捷键和其他辅助功能的支持,

  • 有人能帮我创建balow图像剪切搜索栏吗?我已经用自定义拇指和分段文本浏览过SeekBar,还有SeekBar拇指位置问题 但是我没有成功创建我的客户搜索栏,请帮助我

  • 问题内容: 我正在使用Axis2 1.5.2和Eclipse。我正在使用Eclipse从生成的WSDL生成WSDL和客户端代码。 我创建了一个服务可以抛出的自定义异常。创建Web服务时一切正常。Web服务成功启动,并且可以通过指向Web浏览器来查看生成的WSDL。但是,当我告诉Eclipse使用生成的WSDL生成客户端代码时,我从Eclipse中得到了以下错误: 我的自定义异常是“ InsertU

  • 问题内容: 我需要做的就是在当前函数执行结束时执行一个回调函数。 此功能的使用者应如下所示: 我该如何实施? 问题答案: 实际上,您的代码将按原样工作,只需将回调声明为参数即可,您可以使用参数名称直接调用它。 基础知识 那会叫,这会叫,这会提醒“东西在这里”。 请注意,传递函数 引用 ()而不是调用函数并传递其结果()非常重要。在您的问题中,您可以正确执行此操作,但是值得指出,因为这是一个常见错误

  • 在一次采访中,我最近被问到以下问题: 有没有其他方法可以创建自定义的,而不使用: 扩展异常类或的子类,用于检查异常 为未检查的异常扩展或的子类。 可能的答案是什么?

  • 我创建了一个小的测试项目来测试我的实现,下面是我的异常类头文件。 异常类的源文件为 在我的主应用程序中,我调用了一个函数,该函数抛出我的异常,并在try/catch中捕获它,如下所示: 现在要跑了。哦,天哪,我需要抛出一个异常 捕获的异常:这是我的异常错误。:( 相反,我得到的是 从我在各种帖子上看到的情况来看,我所做的是正确的,所以我错过了什么。