16
Encrypting Spring 3 Java Based Configurations Values With Jasypt
2 Comments · Posted by chrislovecnm in Java
Since I have gotten a TON of comments and traffic in regards to my intial spring configuration post located here, I thought I would add another post about spring config and @values.
Encrypting passwords is always a pain in the butt. No other way to put it. To add insult to injury we needed to encrypt a password with-in a spring based web application. Well jasypt (Java Simplified Encryption) project to the rescue. They support basic spring property value replacement of encrypted value with-in spring 2.0 supported xml out of the box.
You have nothing special to do to integrate Jasypt with Spring, as all of the encryption tools (digesters and encryptors) in jasypt have the adequate design to be correctly instantiated and dependency-injected from a Spring application context. 1
I have created a properties loader that supports spring 3.0 @value injection. On to the examples that can be d/l from my github repo.
Basic Spring Config
<bean id="environmentVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentPBEConfig"
p:algorithm="PBEWithMD5AndDES" p:passwordSysPropertyName="APP_PASS" />
<bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor"
p:config-ref="environmentVariablesConfiguration" />
<bean id="propertyConfigurer"
class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer"
p:locations-ref="passwordProps">
<constructor-arg ref="configurationEncryptor" />
</bean>
<util:list id="passwordProps">
<value>classpath:/cnm.properties</value>
</util:list>
<bean id="testBean" class="test.beans.BeanTestImpl" p:foo="${cnm.foo}" />
In this example, the encryption password will be read from an system variable called “APP_PASS”. This is the password that is used to decrypt encrypted values. The EncryptablePropertyPlaceholderConfigurer will read the cnm.properties file and make its values accessible as ${vars}. A “configurationEncryptor” bean (which implements org.jasypt.encryption.StringEncryptor) is set as a constructor arg.
Simple Spring Unit Test
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:/applicationContext-jasypt.xml"})
public class BasicJasyptTest {
@Autowired
private ITestBean testBean;
@BeforeClass
public static void setupEnvVar() {
System.setProperty("APP_PASS", "151987thisismysalt!!");
}
@Test
public void testBean() {
assertThat(testBean.getFoo(), equalTo("MyPassword"));
}
}
The above test creates the spring application context and injects the decrypted values correctly. The jaspypt beans are using a system property that contains the password that is used to decrypt the values. When the context is created the jasypt components loads and decrypts the properties values that are delimited with the ‘ENC()’ marker.
For example:
- cnm.username=clove is left alone
- cnm.foo=ENC(1FTzaim1KT6w12vRRyCICP/6lPklg1Jw) is decrypted
Well that is awesome and all … but very XML intensive, and not cool enough for me. So lets move on to using @value’s in spring 3.0.
Spring Config Using 3.0 Contexts
<context:component-scan base-package="test.beans" /> <bean id="pbeConfig" class="net.cnmconsulting.spring.config.util.FileStringPBEConfig" p:algorithm="PBEWithMD5AndDES" p:passwordName="classpath:/cnm.token"> </bean> <bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor" p:config-ref="pbeConfig" /> <bean id="propertyConfigurer" class="org.jasypt.spring.properties.EncryptablePropertyPlaceholderConfigurer" p:locations-ref="passwordProps" p:searchSystemEnvironment="true"> <constructor-arg ref="configurationEncryptor" /> </bean> <bean id="props" class="net.cnmconsulting.spring.config.PropertiesFactoryBean" p:locations-ref="passwordProps"> <constructor-arg ref="configurationEncryptor" /> </bean> <util:set id="passwordProps"> <value>classpath:/cnm.properties</value> </util:set>
So two new components are in the spring config above. First we are using context:component to load beans automatically, and secondly our PropertiesFactoryBean is being used that allows for @value injections. Let’s look at part of the the bean.
Spring Bean with encrypted @value
@Service("propTest")
public class PropTestBeanImpl implements PropTest {
@Value("#{props['cnm.username']}")
protected String username;
@Value("#{props['cnm.foo']}")
protected String password;
The bean is pretty self explanatory. Set the cnm.foo value to the field password, and this is what the PropertiesFactoryBean does.
Let’s test it!
Spring Bean Unit Test for Encypted @Value
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:/applicationContext-cmn-props.xml"})
public class CNMPropertiesFactoryBeanTest {
// Inject the bean for testing
@Autowired
private PropTest propTest;
@BeforeClass
public static void setupEnvVar() {
System.setProperty("APP_PASS", "151987thisismysalt!!");
}
/*
* Test will assure that the propTest bean will have the correct values injects,
* and the encypted values are decrypted upon injection
*/
@Test
public void testProp() {
assertNotNull(propTest.getUsername());
assertThat(propTest.getFoo(), equalTo("MyPassword"));
assertThat(propTest.getUsername(), equalTo("clove"));
}
}
As you can see the propTest bean is tested to ensure that the password and username are set correctly.
Again the examples are located in my github repo. Please download fork and improve!
In closing let me mention that jasypt (Java Simplified Encryption) project is very useful and wraps multiple encryption components very elegantly. Check out the feature list. Also you may wonder, how the heck do I create the encrypted passwords using jasypt. My PropertyAppContextReplaceTest unit test provides an example.
Configuration · Encryption · Spring · Value
2 comments
Leave a Reply
<< Gentoo Tip – Emerging Git so that it works with Subversion
Matt · November 2, 2011 at 1:59 am
Thanks, pretty helpful. Might also be helpful to post a copy of your custom PropertiesFactoryBean. I eventually figured out how to create my own after searching the web for another solution first.
Admin comment by chrislovecnm · November 28, 2011 at 10:56 pm
Is that not on my github account? https://github.com/chrislovecnm/Blog-Projects