It’s extremely hard to remember that everything is not a nail. Whenever I’m using Hibernate Core and/or Hibernate Search, I plan on caching frequently used entities, in order to remove unnecessary load on the data-store(s). Pretty standard performance move. I tend to use Ehcache – currently on 1.7.
My latest problem arose when I decided that Spring Security’s DaoAuthenticationProvider should get as much of its information from a cache. Well, if you never change a user’s security information after they are logged in (ya know, like a password) this is fine. However, it’s actually fairly common that a user forgets their password. In some cases, a user might just want to change their password. In either case, if the DaoAuthenticationProvider is looking to a cache for its user data, it will deem the old password to be correct, at least until the cached entity expires. It took me 2 full days to figure this out. I assumed the bad data was being cached, but I could not find the source… I focused on Hibernate for the longest. I thought, maybe a forced flush? No? OK, how about making sure the cache-mode is set to Ignore. No? Hmm, what the heck?!
In the end, I just started looking for all forms of caching in the system. I finally stumbled upon my various DaoAuthenticationProvider Spring definitions, and their userCache dependencies. I went to to the Spring Security documentation and found out that because of this very issue, only stateless apps should use the non-default userCache. Ehh, live and learn…
At a former employer we used a time limited cache for user sign in. You normally don’t change user roles very often. On change password we had that record refreshed in the cache. That site had a high volume on concurrent users and going to the database all the time was not efficient.
http://static.springsource.org/spring-security/site/apidocs/org/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.html
As you can see in the documentation above, Spring already looks at the UserDetails object, which is in the user’s session. So, as long as the application held state (e.g.: HttpSession), that cache served as an obstacle rather than a help.