[ 
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)

Reply via email to