Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hide datasource password in spring xml file

there is a way to hide/encrypt password in xml spring config file? I read that is possible with a "custom" subclass of DataSource, but the solutions keep key in same config file as plain text...so is a bit useless.

There is a way to use KeyStore for this? For example read the value from a keystore.

Thanks all.

like image 636
blow Avatar asked Nov 16 '10 16:11

blow


3 Answers

What is the purpose of hiding the password? I suggest you configure the datasource in the container (Tomcat, JBoss or whatever you use) and inject the datasource into your application using jndi:

<jee:jndi-lookup id="thedatasource"
                     jndi-name="java:comp/env/jdbc/thedatasource"
                     lookup-on-startup="false"
                     expected-type="javax.sql.DataSource"/>

This way you have not to expose and password in your application but only in the servlet container.

like image 84
ordnungswidrig Avatar answered Sep 19 '22 16:09

ordnungswidrig


Yes, you can do that. You will have to create a wrapper bean around the data source class. Here is an example of how I have done it before. Hope this helps!

<beans>
    <bean id="someDao" class="com.dao.SomeDAOImpl">
         <property name="datasource">
            <ref local="secureDataSource"/>
        </property>
    </bean>
    <bean id="secureDataSource" class="com.ds.SecureDataSource">
        <property name="driverClassName">
            <value><your driver></value>
        </property>
        <property name="url">
            <value><your url></value>
        </property>  
        <property name="username">
            <value><your user id></value>
        </property>
        <property name="password">
            <value><encrypted_pwd></value>
        </property> 
    </bean> 
</beans>

Then inside the SecureDataSource class you will need to decrypt the password.

import java.sql.Connection;
import java.sql.SQLException;


public class SecureDataSource extends DriverManagerDataSource{

    private String url;
    private String username;
    private String password;
    /**
     * @param url the url to set
     */
    public void setUrl(String url) {
        this.url = url;
    }

    /**
     * @param username the username to set
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     * @param password the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }

    protected Connection getConnectionFromDriverManager() throws SQLException {
        String decryptedPassword = null;
        //decrypt the password here
        return getConnectionFromDriverManager(url,username,decryptedPassword);
    }
}
like image 36
CoolBeans Avatar answered Sep 21 '22 16:09

CoolBeans


Good options have been given, another obvious answer is to use the PropertyPlaceholderConfigurer:

<context:property-placeholder
    system-properties-mode="OVERRIDE" 
    location="classpath:database.properties" />

<bean id="dataSource" class="com.whatever.datasource.you.Use">
    <property name="password" value="${database.password}" />
</bean> 

Now you can keep your password either as a property in a properties file (which you might create during deployment if you don't want to have it in the SCM) or as a System Property (which will hopefully also be beyond reach of other developers).

Clarification: create during deployment is somewhat vague. I guess you will have to write an installer that generates the properties file dynamically on the end user's machine, probably coupled with a sign up / log in mechanism.


EDIT: I still haven't figured out who you are hiding the information from. Two theories:

a) People who have access to your source code
b) Your customers

If it's a), then go my way. All other ways can easily be breached by the other developer just starting your application with a debugger (and suddenly he's inside the datasource object and sees the password).

If it's b), then you have no chance, basically. The customer has tons of possibilities to get at your password: debuggers, agents, bytecode manipulation, loadtime weaving etc. Even if he doesn't do any of that, he will just have to attach a port sniffer to get at the password in clear text. The only safe thing to do is have a username / password per customer (never store a global password at your customer's machine).

like image 3
Sean Patrick Floyd Avatar answered Sep 21 '22 16:09

Sean Patrick Floyd