Wednesday, July 4, 2012

Encrypting a Hibernate Configuration File Credentials

A Hibernate configuration file deployed with the Hibernate Application. As a known fact, Hibernate.cfg.xml contains the database credentials which it uses to connect to the database layer. Now, if somebody plays with the config file, your application completely crashes.
Considering this, i was asked to look for something that could be used to encrypt the Hibernate config file, which would make the confidential information secure. After several days of search on the net, I got the solution.
I would be using jasypt (Java Simplified Encryption) libraries, which supports Encryption for all sorts of framework.

Add the libraries jasypt-1.9.0.jar and jasypt-hibernate3-1.9.0.jar (if using hibernate 3), use jasypt-hibernate4-1.9.0.jar if using hibernate 4 instead. to your classpath.

Now, add the following two lines to your hibernate config file.
<property name="connection.provider_class">
      org.jasypt.hibernate.connectionprovider.EncryptedPasswordDriverManagerConnectionProvider
    </property>
    <property name="connection.encryptor_registered_name">
      configurationHibernateEncryptor
    </property>
This adds the jasypt encrypted connection providers  to the hibernate file. You also need to register the encriptor. I have used the generally accepted name configurationHibernateEncryptor.


Having done this, you then need to pass the encrypted passwords to the file. 
Eg,
 <property name="hibernate.connection.password">ENC(dNk7whU8eOdkYPZjRyCUyg==)</property>


How to get the encrypted passwords.??


In the jasypt download, you will get the following structure

jasypt->apidocs
         -> bin
         -> lib

Inside bin there will a batch file encrypt.bat. Ensure that your java path is well set in the environment variable.
run the batch file,

Fig. 1 Encryption using a command line application

You need to pass the text which you need to encrypt and the password. Note the output, replace this above instead of the plain text.

Next, in the HibernateUtil file, add the following lines



         StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
 encryptor.setAlgorithm("PBEWithMD5AndDES");
 encryptor.setPassword(root);
          HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance();
  registry.registerPBEStringEncryptor("configurationHibernateEncryptor", encryptor);

This will register the configurationHibernateEncryptor which we named in the Hibernate config file.


That's all, you have just made the hibernate.cfg.xml password safe.


Bhavin







Tuesday, July 3, 2012

Session Management in Hibernate

Hibernate Session Management is an art. You must know where and how the session needs to be opened or closed. Each session once opened has to be closed, otherwise there will be whole bunch of opened sessions that it would give a permgen exception later.
I have gone through many examples on the Internet, where most of the example suggest opening a session using
HibernateUtil.getSessionFactory().openSession();. Opening a session is fine, but then you need to externally close the session. Moreover, each time you open a session, a new instance of session is created.
So, what should be the possible solution?

The R&D which i have done suggest me to have a single session per request. i.e. as a request comes, I open a session, and when all the work is over, I close the session. Then what shall be the difference in this statement and the above.

I'll  give you the difference. In the previous way of getting sessions, there might be possible that updates are done in two different session, where the state of the database is different in both session. There may be possiblity of loss of data, or maybe additional data which is not required may creep in.

To avoid,
in the hibernate.cfg.xml file, add the following two lines

 <property name="hibernate.current_session_context_class">thread</property>
  <property name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

This ensures that the session is a thread safe session, which will be create once and shared everywhere.
In the doGet() or doPost() open a session using
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
and begin a transaction in servlet itself.
Transaction tx = session.beginTransaction();

Call the utility methods that you want to call from the servlets.

In each of the method, get the current session and begin a tranasaction.(even for a method), but this time, you are not creating a new session, but are using the already created session.

so suppose you have a method where in you are persisting the request data
In the method, open the session with

    session = HibernateUtil.getSessionFactory().getCurrentSession();
    tx = session.beginTransaction();

Remember where to commit the transaction because commiting the transaction automatically closes the session, with auto flushing the contents into the database.


So, if the call is suppose you are calling the method from the servlet, to save the inputs.
At the last statement of the method, you are commiting the transaction. then this would mean that session also is closed.
and then for any other purpose, you need to open the session again.

So, I suggest, you first understand where all you need to persist and use the data. I personally believe that commiting the transaction for this should be done exculsively in the servlet,s destroy method or finally block . because that's the only place where we can ensure that all the work would be over for that session and whatever data that has been processed in the data needs to be dumped into the database.

Bhavin.