Using ThreadLocal to bypass servlet security?

I am debugging some old servlet with a lot of exceptions. No ConcurrentModificationExceptions due to the many (too many) synchronized keywords, but I still suspect that the servlet problem is not needed. I read this very interesting question about servlets and thread safety and I think this example is a good base:

public class ExampleServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}

Actually, the people who encoded my servlet also knew about this, but decided to get around it by doing something like this:

public class ExampleServlet extends HttpServlet {

    private ThreadLocal<MyObject> thisIsMaybeThreadSafe = new ThreadLocal<MyObject>();;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // we want to avoid having to use this parameter in every method
        thisIsMaybeThreadSafe.set((MyObject)getObjectInSesssion("foo"));
        doStuff(request, response);
    } 
}

And the code also contains things like

synchronized(request.getAttribute("foo")){
   doStuff(request, response);
}

, , . NullPointerException , - , , :

11:07:17,525 ERROR [com.mycompany.myproject.web.business.servlet.map.tree.MapServlet] Error processing AjaxTreeAccessRequest
java.lang.NullPointerException
    at org.apache.catalina.connector.Request.notifyAttributeAssigned(Request.java:1493)
    at org.apache.catalina.connector.Request.setAttribute(Request.java:1484)
    at org.apache.catalina.connector.RequestFacade.setAttribute(RequestFacade.java:539)
    at javax.servlet.ServletRequestWrapper.setAttribute(ServletRequestWrapper.java:244)
    at org.apache.myfaces.context.servlet.RequestMap.setAttribute(RequestMap.java:51)
    at org.apache.myfaces.util.AbstractAttributeMap.put(AbstractAttributeMap.java:108)
    at org.apache.myfaces.el.VariableResolverImpl.resolveVariable(VariableResolverImpl.java:304)
    at org.springframework.web.jsf.DelegatingVariableResolver.resolveOriginal(DelegatingVariableResolver.java:120)
    at org.springframework.web.jsf.DelegatingVariableResolver.resolveVariable(DelegatingVariableResolver.java:105)
    at com.mycompany.myproject.web.common.servlet.AbstractFacesServlet.getManagedBean(AbstractFacesServlet.java:67)
    at com.mycompany.myproject.web.business.servlet.map.tree.MapServlet.getSessionTreeBean(MapServlet.java:184)
    at com.mycompany.myproject.web.business.servlet.map.tree.AjaxTreeAccess.initRequest(AjaxTreeAccess.java:355)
    at com.mycompany.myproject.web.business.servlet.map.tree.AjaxTreeAccess.processRequest(AjaxTreeAccess.java:134)
    at com.mycompany.myproject.web.common.servlet.AbstractFacesServlet.handleRequest(AbstractFacesServlet.java:81)
    at org.springframework.web.context.support.HttpRequestHandlerServlet.service(HttpRequestHandlerServlet.java:63)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.mycompany.myproject.commun.presentation.jsf.OpenSynchronizedSessionInViewFilter.doFilterInternal(OpenSynchronizedSessionInViewFilter.java:58)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
    at com.mycompany.myproject.web.common.filter.SwitchUserProcessingFilter.doFilter(SwitchUserProcessingFilter.java:66)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:81)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:229)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:286)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
    at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.mycompany.myproject.web.business.filter.UserBindingFilter.doFilter(UtilisateurCourantBindingFilter.java:55)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.mycompany.myproject.web.common.filter.SessionTimeoutFilter.doFilter(SessionTimeoutFilter.java:67)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.mycompany.myproject.web.common.filter.SessionLoginFilter.doFilter(SessionLoginFilter.java:56)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.mycompany.profiling.prof.filter.ProfContextFilter.doFilter(ProfContextFilter.java:26)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:655)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:744)

ThreadLocal, , , , .

FYI. spring -JSF, ThreadLocal JSF beans. , ?

+4
2
  • synchronized(request.getAttribute("foo")) , foo, NPE. .
  • ThreadLocal - , . , , , , , , ( ) ( , API- Servlet concurrency), .

, :)

+2

ThreadLocal .

ThreadLocal MyObject , . .

, , , , Thread .

, , ( , ), , concurrency, , MyObject .

, . , .

, , , , doGet. ?

0

All Articles