Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shiro in a multi-threaded environment

The basic way that I understand Shiro's SecurityUtils.getSubject() to work is that it returns the subject which is bound to the currently executing thread. However, this just seems at odds with a servlet container like Tomcat which is using a thread pool to service requests.

If Tomcat is say using ThreadA to handle requests, any calls to SecurityUtils.getSubject() should work fine. But, as soon as ThreadB is selected, the user is lost, getSubject returns null and isAuthenticated is now false. This is even though the user is still logged in.

I have confirmed this in my application. I am using Shiro Core 1.2 and notice that my user is just miraculously being inauthenticated when I navigate through my app. If I look at the logs, the problem happens as soon as a different thread is used to service the request.

So, do I have Shiro configured incorrectly? It seems like the 'current user' should be bound to something a bit more longer-lasting than the current thread. I would expect it to be session-based. I know that Shiro has session management, but in all examples I've found, it says to get the current user by calling getSubject, which looks at the ThreadContext. Am I missing something?

like image 642
sma Avatar asked Mar 22 '12 20:03

sma


1 Answers

So, it turns out that I just didn't have Shiro configured correctly. I have a web app, yet I was setting up the Security Manager in code. This resulted in the Security Manager being set up on a certain thread only. As long as requests were serviced by that same thread, it worked fine. But as soon as Tomcat chose a different thread, the user appeared inauthenticated.

Shiro has a filter for web apps that handles this scenario and binds the user to each incoming request. You should have your app configured as follows instead of doing the security manager in code:

<context-param>
    <param-name>shiroConfigLocations</param-name>
    <param-value>classpath:auth.ini</param-value>
</context-param>

<!--  Shiro Environment Listener -->
<listener>
    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>

<!--  Shiro Filter Configuration -->
<filter>
    <filter-name>ShiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>ShiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
like image 108
sma Avatar answered Oct 09 '22 14:10

sma