access a property within a custom PropertyPlaceholderConfigurer - spring

We are on Spring 4.2.5 version. There is a need to have a custom implementation of PropertyPlaceholderConfigurer basically to have data decrypted before using them. This works fine. However I further need to be able to change the crypto mechanism used within this custom implementation, based on a property (read using the normal context:property-placeholder). Is there a way to get this working?

The easiest way to do that is not to have a custom PropertyPlaceholderConfigurer, but a custom DefaultPropertiesPersister. This is configured this way :
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:...</value>
<value>...</value>
</list>
</property>
<property name="propertiesPersister">
<bean class="yourPropertiesPersister"/>
</property>
...
</bean>
Then yourPropertiesPersister needs to extends DefaultPropertiesPersister which makes you implement :
public void load(Properties props, InputStream is) throws IOException {
super.load(props, is);
decrypt(props);
}
#Override
public void load(Properties props, Reader reader) throws IOException {
super.load(props, reader);
decrypt(props);
}
private void decrypt(Properties props) {
// your logic here
}
The call to super.load(...) will load the raw properties (content is not decrypted). Just add the logic to a method decrypt(props), based on the content of some of the properties. Add your decrypted properties to props.

Your use case is covered by the jasypt library, if you don't mind adding one more dependency to your project. What makes it neat is the fact that it integrates seamlessly with Spring and it facilitates further changes in the parameterization of your encryption, i.e. the algorithm used or the location of the master encryption key.
What is cool is that the code in your spring config / class annotations, in which you inject the value corresponding to a certain key in a property file, will look the same, as if you're using plain-text properties.
Here is a small example, as per the tutorial in their website (http://www.jasypt.org/spring31.html):
application.properties => your properties file
datasource.driver=com.mysql.jdbc.Driver
datasource.url=jdbc:mysql://localhost/reportsdb
datasource.username=reportsUser
datasource.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm)
your Spring config (works the same when injecting through annotations)
<!-- -->
<!-- Configuration for encryptor, based on environment variables. -->
<!-- -->
<!-- In this example, the encryption password will be read from an -->
<!-- environment variable called "APP_ENCRYPTION_PASSWORD" which, once -->
<!-- the application has been started, could be safely unset. -->
<!-- -->
<bean id="environmentVariablesConfiguration"
class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
<property name="algorithm" value="PBEWithMD5AndDES" />
<property name="passwordEnvName" value="APP_ENCRYPTION_PASSWORD" />
</bean>
<!-- -->
<!-- The will be the encryptor used for decrypting configuration values. -->
<!-- -->
<bean id="configurationEncryptor"
class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="config" ref="environmentVariablesConfiguration" />
</bean>
<!-- -->
<!-- The EncryptablePropertyPlaceholderConfigurer will read the -->
<!-- .properties files and make their values accessible as ${var}. -->
<!-- -->
<!-- Our "configurationEncryptor" bean (which implements -->
<!-- org.jasypt.encryption.StringEncryptor) is set as a constructor arg. -->
<!-- -->
<bean id="propertyConfigurer"
class="org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer">
<constructor-arg ref="configurationEncryptor" />
<property name="locations">
<list>
<value>/WEB-INF/classes/application.properties</value>
</list>
</property>
</bean>
<!-- -->
<!-- Our datasource is configured here, in the usual way. Jasypt's -->
<!-- EncryptedPropertyPlaceholderConfigurer will make sure that the -->
<!-- ${datasource.password} file gets decrypted and the DBCP DataSource -->
<!-- will be correctly initialised. -->
<!-- -->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName">
<value>${datasource.driver}</value>
</property>
<property name="url">
<value>${datasource.url}</value>
</property>
<property name="username">
<value>${datasource.username}</value>
</property>
<property name="password">
<value>${datasource.password}</value>
</property>
</bean>
Jasypt parses the content of the property files you've provided and decrypts the values enclosed between ENC( and ). You can find additional details in the link provided above, it is truly a working example.
Another interesting feature of jasypt is the fact that it provides a command line tool, that you can use to encrypt the original, plain-text values, with a plethora of algorithms you can choose from. You can find the concise documentation of this tool here: http://www.jasypt.org/cli.html.

Related

Jasypt with spring framework

I'm trying to set up jasypt to have passwords in .properties files encrypted.
I don't need to encrypt anything on runtime, only decrypt.
My passwords are already encripted in the .properties file like this: some.pass=ENC(aFX0/gUNUbk1TMX0qddowrq23Htqr5Kh8mTwqmx1KA/n3tE=)
After researching I found that I could achieve this with some steps:
-Adding the Jasypt dependency on pom.xml
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.9.3</version>
</dependency>
Then there are two approaches (I think):
1 Use and environment variable (with the decription key) that is set on startup:
-Djasypt.encryptor.password=decryptionKey
2 Use beans:
<bean id="environmentVariablesConfiguration"
class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
<property name="algorithm" value="PBEWithMD5AndDES" />
<property name="passwordEnvName" value="decryptionKey" />
</bean>
<bean id="propertyConfigurer"
class="org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer">
<constructor-arg ref="configurationEncryptor" />
<property name="locations">
<list>
<value>/WEB-INF/classes/application.properties</value>
</list>
</property>
</bean>
My question is how do I actually decrypt my passwords with either one of these approaches. Can I simply use #Value("${some.pass}") String decryptedPassword; ?
I'm quite confused because most of the content that I searching is related to spring boot which is not my case.
Thanks in advance for any help
The solution was addind the pom dependency in pom.xml, then add to the VMoptions in Intellij an environment variable -DAPP_ENCRYPTION_PASSWORD=mykey.
Then I added the following beans:
<bean id="environmentVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
<property name="algorithm" value="PBEWITHMD5ANDDES" />
<property name="passwordSysPropertyName" value="APP_ENCRYPTION_PASSWORD" />
</bean>
<bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="config" ref="environmentVariablesConfiguration" />
</bean>
and then another bean for each environment, for example, for development:
<beans profile="development">
<bean class="org.jasypt.spring4.properties.EncryptablePropertyPlaceholderConfigurer">
<constructor-arg ref="configurationEncryptor" />
<property name="locations">
<list>
<value>/WEB-INF/config/config.properties</value>
<value>/WEB-INF/config/config.development.properties</value>
</list>
</property>
</bean>
<bean id="somethingService" class="doesnt.matter.common.someth.services.api.v1.Something"
p:serverUrl="http://something"
p:rest-ref="restOperations"
p:encryptLoginRequest="true"
p:encryptTokenRequest="true"
p:urlEncoding="ISO-8859-1"
/>
</beans>
where inside the property name="locations" tag I listed every file where encrypted passwords could be found.
Then, in those files I put the encrypted passwords, using this online tool
https://www.devglan.com/online-tools/jasypt-online-encryption-decryption.
for example, in my config.properties file I have a password like:
some.password=ENC(balrcbxgktzeskjvn==)
Finally, in the file where I use the password, I used the #Value annotation like this:
#Value("${some.password}")
private String hiddenPass;

Yaml file has not being recognized in application.context

I´m trying to use yaml instead of properties and in every application context i have, i put the application.yml
<!-- Enable the configuration for utilization of #PropertySource & #Value
annotations -->
<bean
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>classpath:Messages.properties</value>
<value>classpath:application.yml</value>
</list>
</property>
</bean>
However the application doesn´t recognize the file:"Cannot resolve file 'application.yml" and the properties in #Value are not being translated.
I put mannualy the application.yaml in every resource folder but doesn´t work,
what i need to do?
Thanks

Freemarker template not found, spring configuration

I am trying to use freemarker template using spring, my spring config is give below,
<bean id="freemarkerConf" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean" >
<!-- Turn this off to always load via SpringTemplateLoader -->
<property name="preferFileSystemAccess" value="false"></property>
<property name="templateLoaderPath" value="classpath:/WEB-INF/freemarker/alertmail/"></property>
</bean>
but for some reason I keep getting the following exception,
java.io.FileNotFoundException: Template mainMail.ftl not found.
at freemarker.template.Configuration.getTemplate(Configuration.java:489)
at freemarker.template.Configuration.getTemplate(Configuration.java:466)
My code is as below,
mailBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerConf.getTemplate("mainMail.ftl","UTF-8"), model);
My templates are located in a folder under the classpath.
Make sure files are under: src/freemarker/alermail and then
<bean id="freemarkerConf" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean" >
<!-- Turn this off to always load via SpringTemplateLoader -->
<property name="preferFileSystemAccess" value="false"></property>
<property name="templateLoaderPath" value="classpath:/freemarker/alertmail/"></property>
</bean>

Several PropertyPlaceholderConfigurers with spring

I have a strange problem with my spring bean definition. My application is a multi-module thing.
At the moment I have a project named core-lib which has a spring.xml file defining a PropertyPlaceholderConfigurer like this:
<bean id="corePropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="10" />
<property name="locations">
<list>
<!-- default properties files containing ALL possible properties -->
<value>classpath:default.connection.properties</value>
<value>classpath:default.mq.properties</value>
<!-- installation specific, optional properties file containing overridden properties -->
<value>classpath:connection.properties</value>
<value>classpath:mq.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>
Second I have a depending project which has its own spring.xml file including the one from the core-lib project. Moreover it defines a second PropertyPlaceholderConfigurer like this:
<!-- import configuration from service layer -->
<import resource="classpath:spring.xml"/>
<bean id="commPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="20" />
<property name="locations">
<list>
<!-- properties files containing ALL possible properties -->
<value>classpath:processing.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>
Now I have the behavior that a bean defined in this second spring PlaceholderConfigurer can't be instantiated due to missing properties:
BeanDefinitionStoreException: Invalid bean definition with name 'commServer' defined in class path resource [comm-server.spring.xml]: Could not resolve placeholder 'comm.server.CommServer.port'
If I set a breakpoint in the PropertyPlaceholderConfigurer class it only get's triggered for the first bean instance and never for the second. Has anyone had a similar setup and can give me some advice?
Thanks,
Sebastian
There is a more comfortable way by defining a new placeholder prefix and suffix:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:configuration.properties</value>
</property>
<property name="placeholderPrefix" value="myprefix{" />
<property name="placeholderSuffix" value="}" />
</bean>
Found here: http://javalibs.blogspot.co.at/2008/04/java-spring-framework-multiple.html
OK I resolved that myself, although I do not understand why this is working so strange.
I have defined a different prefix in the second placeholder (?{ instead of ${) and now its working. I had expected that this would work without any special prefixes...

using a <jee:jndi-lookup string inside an instance of PropertyPlaceholderConfigurer

Environment: Windows server 2003, Spring 3.0, Tomcat 6
How can I reference a JNDI property inside a PropertyPlaceholderConfigurer?
Specifically, I'm using JNDI to look up a java.lang.String that represents a path to
a property file needed by my webapp
<jee:jndi-lookup id="mypropsfile1" jndi-name="myPropsFile1" resource-ref="true"/>
<jee:jndi-lookup id="mypropsfile2" jndi-name="myPropsFile2" resource-ref="true"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<array>
<value>how to use mypropsfile1 here ??</value>
<value>how to use mypropsfile2 here ??</value>
</array>
</property>
</bean>
My "jee:jndi-lookup"s are working AFAIK. My problem seems to be how to reference JNDI resources
inside the tag pair
Thanks in advance!
Mark
Your approach may not work Mark, this is because PropertyPlaceHolderConfigurer is a BeanFactoryPostProcessor and gets invoked at the point when the bean definitions are created, whereas the jndi lookup happens post this stage.
I saw an older Spring forum discussion item, which has a recommendation for an approach of using a jndi lookup based properties file, which may suit your needs:
I believe you will have to do something like this . I haven't tested it but basically the setLocations method in PropertyPlaceholderConfigurer takes in an array of Resource(In our case UrlResource - http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/core/io/UrlResource.html) which in turn has a constructor with the file path .
<jee:jndi-lookup id="mypropsfile1" jndi-name="myPropsFile1" default-value="file:///C:/defaultPath" resource-ref="true"/>
<jee:jndi-lookup id="mypropsfile2" jndi-name="myPropsFile2" resource-ref="true"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="mypropsfile1,mypropsfile2">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<bean class="org.springframework.core.io.UrlResource">
<constructor-arg><ref bean="mypropsfile1"/></constructor-arg>
</bean>
<bean class="org.springframework.core.io.UrlResource">
<constructor-arg><ref bean="myPropsFile2"/></constructor-arg>
</bean>
</list>
</property>
</bean>
I am not sure if there is a tag called in spring . Check this http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-introduction
I do this in Spring 3 using a map as follows:
<jee:jndi-lookup id="myJndiLookup" jndi-name="com.techtrip.spring.config.myJndiLookup"></jee:jndi-lookup>
<bean id="somethingWithMap" class="com.techtrip.foo.SomethingWithMap">
<property name="propMap">
<map>
<entry key="myJndiLookup" value-ref="myJndiLookup" />
</map>
</property>
</bean>
This works fine in most cases. You may run into trouble if you use AOP or something that wraps the bean in a Proxy class even if you set eager init correctly. A solution in that case is to directly access the somethingWithMap bean from the app context when needed using:
applicationContext.getBeansOfType(type, includeNonSingletons, allowEagerInit);
*Note that this will return a Map<String, T> where you can access the bean by name.
Not exactly for a single JNDI property, this is using a Properties reference instead, obtained through JNDI:
<!-- Lookup Properties reference through JNDI -->
<jee:jndi-lookup id="config-properties" jndi-name="resources/resource-name" resource-ref="true"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="config-properties">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<!-- Once the reference is obtained from JNDI, it can be used like any other reference -->
<property name="properties" ref="config-properties"></property>
</bean>

Resources