Threads are pooled, so you need to ensure to clear the ThreadLocal out for each request. If you were doing this in a Filter it might look something like this:
private static final ThreadLocal<String> CONTEXT = new ThreadLocal<String>();
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
try {
CONTEXT.set(userName);
chain.doFilter(req,res);
} finally {
CONTEXT.remove();
}
}
Otherwise what might happen is:
- UserA logs in and is associated to ThreadA (UserA is in the context)
- UserB logs in and is associated to ThreadB (UserB is in the context)
- UserA's session times out and no longer has user information associated to his session
- UserA uses ThreadB and then since ThreadB is used again, it appears UserB is in the context)
Not only is this a security issue, but it is also a memory leak. While only one per Thread that is populated with a user seems pretty small it can add up. Additionally, if the object placed in the ThreadLocal is an Object that the type belongs to the war's ClassLoader you will have a large PermGen leak that leaks the entire contents of your war each time your application is undeployed/deployed without restarting your application server.
@LaurentG is correct that the approach to use with Spring Security is to use the SecurityContextHolder. You can see that the SecurityContextPersistenceFilter ensures the SecurityContext gets cleared out in a finally block.