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?
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With