I want to keep encoded password in my below mentioned springApplicationContext.xml
Is there any way to achieve this?
presently I have configured all properties using property-placeholder as shown below but the raw password is still open in my database.properties
springApplicationContext.xml
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<beans:property name="driverClassName"><beans:value>${db.driverClassName}</beans:value></beans:property>
<beans:property name="url"><beans:value>${db.url}</beans:value></beans:property>
<beans:property name="username"><beans:value>${db.username}</beans:value></beans:property>
<beans:property name="password"><beans:value>${db.password}</beans:value></beans:property>
</beans:bean>
but actual values are present in my database.properties
db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost/myDB
db.username=root
db.password=root
I want something like below:
springApplicationContext.xml (same as above)
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<beans:property name="driverClassName"><beans:value>${db.driverClassName}</beans:value></beans:property>
<beans:property name="url"><beans:value>${db.url}</beans:value></beans:property>
<beans:property name="username"><beans:value>${db.username}</beans:value></beans:property>
<beans:property name="password"><beans:value>${db.password}</beans:value></beans:property>
</beans:bean>
But password property value should be in encripted format in my database.properties
db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost/myDB
db.username=root
db.password=3g6n72ef8x (using any encription method).
and my dataSource internally decrypt the password before making new DB connection.
Highly appreciate for any help/suggestion in this.
Its might be funny that I am answering to my own question. but still I just wanted to tell my solution, others who might have faced same kind of issue..
for simplicity I have used BASE64Encoder & BASE64Decoder. later I will modify my code to use a secure/better encryption/decryption algorithm.
I have encoded my database password(ex: root for my case) by using the below code:
private String encode(String str) {
BASE64Encoder encoder = new BASE64Encoder();
str = new String(encoder.encodeBuffer(str.getBytes()));
return str;
}
and placed the encoded password in my database.properties file like below:
before
db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost/myDB
db.username=root
db.password=root
after
db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost/myDB
db.username=root
db.password=cm9vdA== (Note: encoded 'root' by using BASE64Encoder)
Now I have written a wrapper class for org.apache.commons.dbcp.BasicDataSource and overridden setPassword() method:
import java.io.IOException;
import org.apache.commons.dbcp.BasicDataSource;
import sun.misc.BASE64Decoder;
public class MyCustomBasicDataSource extends BasicDataSource{
public CustomBasicDataSource() {
super();
}
public synchronized void setPassword(String encodedPassword){
this.password = decode(encodedPassword);
}
private String decode(String password) {
BASE64Decoder decoder = new BASE64Decoder();
String decodedPassword = null;
try {
decodedPassword = new String(decoder.decodeBuffer(password));
} catch (IOException e) {
e.printStackTrace();
}
return decodedPassword;
}
}
This way I am decoding(BASE64Decoder) the encoded password provided in database.properties
and also modified the class attribute of my dataSource bean mentioned in springApplicationContext.xml file.
<beans:bean id="dataSource" class="edu.config.db.datasource.custom.MyCustomBasicDataSource" destroy-method="close">
<beans:property name="driverClassName"><beans:value>${db.driverClassName}</beans:value></beans:property>
<beans:property name="url"><beans:value>${db.url}</beans:value></beans:property>
<beans:property name="username"><beans:value>${db.username}</beans:value></beans:property>
<beans:property name="password"><beans:value>${db.password}</beans:value></beans:property>
Thanks.
Create customized PropertyPlaceHolderConfigurer extending Spring PropertyPlaceHolderConfigurer
public class PropertyPlaceholderConfigurer extends
org.springframework.beans.factory.config.PropertyPlaceholderConfigurer {
@Override
protected String convertPropertyValue(final String originalValue) {
if (originalValue.startwith("SomeText:")) {
//Apply the decryption logic
...
}
}
}
You can encrypt the properties and append SomeText:. Use this customized PropertyPlaceHolderConfigurer to load the properties
Create a wrapper class implementing the Datasource
interface which delegates it's method calls to the underlying datasource but decrypts the password before doing so.
I'd like to look at the larger picture here: why do you want to encrypt values in your properties file? What is your scenario where unauthorized people have access to your properties file?
A usual technique to deal with this larger problem of storing production credentials is to make credentials a part of your environment as opposed to part of your source code. Here are some ways to do this:
- Placing the properties file (with plaintext passwords) on the classpath of the web server in production, this way access to that password is controlled by access to the production machine.
- Store properties in web.xml (context-param with param-name), again this file is part of the environment in which you run your code and not distributed with your code - access to that file is controlled by access to the machine.
- Use JNDI and configure that resource in your application server.
If you are using tomcat connection pool as data source, here is an implementation
http://www.jdev.it/encrypting-passwords-in-tomcat/
Create a class which extends org.apache.tomcat.jdbc.pool.DataSourceFactory and configure it in the server.xml
来源:https://stackoverflow.com/questions/12834604/using-encoded-password-for-the-datasource-used-in-spring-applicationcontext-xml