简体   繁体   中英

Jasypt Encryption not working with Maven profiles

I'm trying to get jasypt to decrypt a (previously encrypted) property value, which ultimately will be used to log into a database. The decryption works fine except for when I introduce Maven profiles. I have a local/dev/prod set of property files which are environment specific.

Here's the relevant portion of my spring3 config. This is the most critical part of the code examples: this is driving how the decryption is setup and what decrypted string is being set to the example dummy bean.

  <bean id="jvmVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentPBEConfig"
         p:password="secret_password_here"/>

  <bean id="jvmConfigurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor"
        p:config-ref="jvmVariablesConfiguration"/>

  <bean id="jvmPropertyConfigurer" class="org.jasypt.spring3.properties.EncryptablePropertyPlaceholderConfigurer"
        p:locations-ref="passwordProps">
    <constructor-arg ref="jvmConfigurationEncryptor"/>
  </bean>

  <util:list id="passwordProps">
    <value>classpath:database.properties</value>    
  </util:list>

  <encryption:encryptable-properties id="dbProps" encryptor="jvmConfigurationEncryptor" location="classpath:database.properties"/>

  <bean id="dummy" class="DummyPropertyTest">
    <property name="prop" value="${database.bar}"/>
  </bean>

In one of my maven poms, here is where I specify the profiles.

  ...

  <profiles>
    <profile>
      <id>local</id>
      <properties>
        <build.profile.id>local</build.profile.id>
      </properties>
      <build>
        <filters>
          <filter>src/main/resources/properties/${build.profile.id}/database.properties</filter>
        </filters>
        <resources>
          <resource>
            <filtering>true</filtering>
            <directory>src/main/resources</directory>
            <includes>
              <include>**/*.properties</include>
              <include>**/*.xml</include>
            </includes>
          </resource>
        </resources>
      </build>
    </profile>

    <!--dev and prod profiles follow this in a similar pattern -->

....

I'm using jasypt version 1.9.1:

<dependency>
  <groupId>org.jasypt</groupId>
  <artifactId>jasypt-spring3</artifactId>
  <version>1.9.1</version>
</dependency>

I have a main database property file (database.properties) setup in /src/main/resources, which has these placeholder properties:

database.url=${database.url}
database.username=${database.username}
database.password=${database.password}
database.dialect=${database.dialect}
database.driver=${database.driver}
database.show_sql=${database.show_sql}
database.bar=${database.bar}

And then here's my local property file, located at /src/main/resources/properties/local/database.properties :

database.url=jdbc:hsqldb:hsql://localhost/db
database.username=sa
database.password=
database.dialect=MyHSQLDialect
database.driver=org.hsqldb.jdbcDriver
database.show_sql=true
database.bar=ENC(RSuprdBgcpdheiWX0hJ45Q==)

Here's my sample spring bean code, simply reading the property that was set to it. If everything works, the value will be printed to stdout decrypted.

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DummyPropertyTest {

    private String prop;

    public String getProp() {
        return prop;
    }

    public void setProp(String prop) {
        this.prop = prop;
    }

    @Value("#{dbProps['database.bar']}")
    public String otherProp;

    public String getOtherProp() {
        return otherProp;
    }

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext-common.xml");
        DummyPropertyTest dpt = (DummyPropertyTest) ctx.getBean("dummy");

        System.out.println("what's my property being set??: "+dpt.getProp());
        System.out.println("otherProp:"+dpt.getOtherProp());
    }
}

If I tweak my spring configuration to read in a property that resides on the main property file which normally just contains just placeholders for the per-property environment override, then the decryption works. But the decryption does not work trying to read a encrypted property from the local properties file. I've mucked around quite a bit trying to tweak the spring configurations, hoping that perhaps it was just a classpath issue, but that didn't seem to help either.

Do I need to override how Spring looks at property prefixes and suffixes, if only for perhaps the properties i need to encrypt? (If I do that, that would seem to be applicable to all properties, not just the encryptable ones, since Jasypt's EncryptablePropertyPlaceholderConfigurer is a drop-in replacement for Spring's PropertyPlaceholderConfigurer).

Here's the output of the program if I have the two properties files set as I've illustrated: what's my property being set??: ENC(RSuprdBgcpdheiWX0hJ45Q==)

Here's the output of the program if I have the main property file contain the encrypted property: what's my property being set??: sa

I'm not sure if the problem is Spring, or Jayspt. I don't think it's Maven. I'd rather not ditch the Maven profiles as they stand now, if at all possible.

Edited for clarity, runtime examples.

* Update * : I can verify that the value is correctly decrypted if I use the Jasypt Spring configuration way <encryption:encryptable-properties id="dbProps" encryptor="jvmConfigurationEncryptor" location="classpath:database.properties"/>

Then in my test Bean I can wire up a member to have the property assigned to it:

    @Value("#{dbProps['database.bar']}")
    public String otherProp;

This seems to work. But I really need the PropertyOverride thing to work, so that I can properly get the database configuration buttoned up.

I figured out the solution with help from a coworker. The problem was indeed the maven filtering of the profiles. Here's the corrected profile setup. After that, decryption worked like a dream. So, no need for the separate wiring of the @Value annotation directly into the bean: setting the property directly from the Spring config worked fine.

<profile>
  <id>local</id>
  <properties>
    <build.profile.id>local</build.profile.id>
  </properties>
  <build>
    <filters>
      <filter>src/main/resources/properties/${build.profile.id}/database.properties</filter>
      <filter>src/main/resources/properties/${build.profile.id}/cli.properties</filter>
    </filters>
    <resources>
      <resource>
        <filtering>true</filtering>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.properties</include>
        </includes>
        <excludes>
          <exclude>**/*.xml</exclude>
          <exclude>**/local/*.properties</exclude>
          <exclude>**/dev/*.properties</exclude>
          <exclude>**/prod/*.properties</exclude>
        </excludes>
      </resource>
      <resource>
        <filtering>false</filtering>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
      </resource>
    </resources>
  </build>
</profile>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM