[
https://issues.apache.org/jira/browse/SHIRO-578?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Stephen McCants updated SHIRO-578:
----------------------------------
Attachment: ShiroRace2.war
Attaching simple web application's WAR file with source code.
> Race condition between Session.touch() and AbstractValidatingSessionManager.
> ----------------------------------------------------------------------------
>
> Key: SHIRO-578
> URL: https://issues.apache.org/jira/browse/SHIRO-578
> Project: Shiro
> Issue Type: Bug
> Components: Session Management
> Affects Versions: 1.2.2, 1.3.0
> Reporter: Stephen McCants
> Attachments: ShiroRace2.war
>
>
> I think I've found a race condition using Shiro 1.3.0 and a trivial web
> application between Session.touch() and the
> AbstractValidatingSessionManager.validateSessions(). The reason I'm looking
> that this code so carefully for race conditions is that our production web
> site sees the occasional (a few a week) UnknownSessionException in a way that
> is likely presenting the user with a 500 error screen.
> I set my breakpoints at SimpleSession.touch() and
> AbstractValidatingSessionManager.validateSession().
> Here are the steps to reproduce:
> # I login, which creates my session and takes me to my default Servlet/JSP.
> # I refresh my web page, which will hit the Servlet again, but I stop at the
> "touch" breakpoint.
> # I wait for the ExecutorServiceSessionValidationScheduler to hit my
> breakpoint in AbstractValidatingSessionManager.
> # Step through and let AbstractValidatingSessionManager.validateSession()
> invalidate my session and delete it because it is expired.
> # Resume at the "touch" breakpoint and I get a 500 error page with
> UnknownSessionException:
> It really seems like there could be a race condition were a user reloads a
> web page right as their session is expiring. The user get the session, but
> the ExecutorServiceSessionValidationScheduler immediately invalidates it
> before the user can "touch" it. This results in the Servlet failing if it
> needs something out the Session (such as the Principal - it has no problem
> retrieving the Subject).
> Here is my shiro.ini file:
> {code}
> [main]
> cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
> securityManager.cacheManager = $cacheManager
> # Set the timeout to one minute, so we don't have to wait so long
> sessionDAO = org.apache.shiro.session.mgt.eis.MemorySessionDAO
> sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
> sessionManager.globalSessionTimeout = 60000
> sessionManager.sessionDAO = $sessionDAO
> securityManager.sessionManager = $sessionManager
> sessionValidationScheduler =
> org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler
> sessionValidationScheduler.interval = 60000
> sessionValidationScheduler.sessionManager = $sessionManager
> securityManager.sessionManager.sessionValidationScheduler =
> $sessionValidationScheduler
> #securityManager.sessionManager.sessionValidationInterval = 6000
> securityManager.sessionManager.sessionValidationSchedulerEnabled = true
> testRealm = com.hcs.shiro.race.TestRealm
> testFilter = org.apache.shiro.web.filter.authc.FormAuthenticationFilter
> testFilter.loginUrl = /login.jsp
> testFilter.usernameParam = j_username
> testFilter.passwordParam = j_password
> testFilter.rememberMeParam = rememberMe
> testFilter.successUrl = /myAccount
> logout = org.apache.shiro.web.filter.authc.LogoutFilter
> logout.redirectUrl = /login.jsp
> # Permission
> [urls]
> /logout = logout
> /** = testFilter
> {code}
> As you can see, the only custom code I'm using is the TestRealm, which
> authenticates anyone who provides a username and password.
> Here is my trivial Servlet:
> {code}
> protected void doGet(HttpServletRequest request, HttpServletResponse
> response) throws ServletException, IOException {
> Subject subject = SecurityUtils.getSubject();
> Object principal = subject.getPrincipal();
> request.setAttribute(ATTR_PRINCIPAL, principal.toString());
> ServletContext context = getServletContext();
> RequestDispatcher dispatcher =
> context.getRequestDispatcher("/myAccount.jsp");
> dispatcher.forward(request, response);
> }
> {code}
> It fails on "subject.getPrincipal()" in the scenario described above and has
> been seen to fail in my production code in a similar line with a similar
> error message.
> Here is the exception:
> {noformat}
> org.apache.shiro.session.StoppedSessionException: Session with id
> [1c59c589-2920-4ba6-b3c8-118997110844] has been explicitly stopped. No
> further interaction under this session is allowed.
>
> org.apache.shiro.session.mgt.SimpleSession.validate(SimpleSession.java:270)
>
> org.apache.shiro.session.mgt.AbstractValidatingSessionManager.doValidate(AbstractValidatingSessionManager.java:186)
>
> org.apache.shiro.session.mgt.AbstractValidatingSessionManager.validate(AbstractValidatingSessionManager.java:143)
>
> org.apache.shiro.session.mgt.AbstractValidatingSessionManager.doGetSession(AbstractValidatingSessionManager.java:120)
>
> org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupSession(AbstractNativeSessionManager.java:148)
>
> org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupRequiredSession(AbstractNativeSessionManager.java:152)
>
> org.apache.shiro.session.mgt.AbstractNativeSessionManager.getAttribute(AbstractNativeSessionManager.java:249)
>
> org.apache.shiro.session.mgt.DelegatingSession.getAttribute(DelegatingSession.java:141)
>
> org.apache.shiro.session.ProxiedSession.getAttribute(ProxiedSession.java:121)
>
> org.apache.shiro.subject.support.DelegatingSubject.getRunAsPrincipalsStack(DelegatingSubject.java:469)
>
> org.apache.shiro.subject.support.DelegatingSubject.getPrincipals(DelegatingSubject.java:153)
>
> org.apache.shiro.subject.support.DelegatingSubject.getPrincipal(DelegatingSubject.java:149)
> com.hcs.shiro.race.MyAccount.doGet(MyAccount.java:30)
> javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
> {noformat}
> Original discussion for in Shiro Users' Group:
> http://shiro-user.582556.n2.nabble.com/Race-condition-between-Session-touch-and-AbstractValidatingSessionManager-td7581196.html
> Note: My trivial test case uses Shiro 1.3.0 code while my production code is
> using 1.2.2.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)