spring-security
spring-security copied to clipboard
Smarter HttpSession Access
Summary
For resources that are public (i.e. images, javascript, css, etc) Spring Security should in many cases be able to avoid accessing the HttpSession. This has a significant implication for applications using Spring Session.
We should make Spring Security smarter about how it accesses the HttpSession.
- [x] gh-7157
- [x] #11453
- [ ] gh-11454
- [x] #11457
- [x] #11456
- [ ] #11455
- [ ] There are other places but stacktraces do not make sense
java.lang.RuntimeException: getSession(false)
at example.SessionAccessedFilter$1.getSession(SessionAccessedFilter.java:25)
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:244)
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:244)
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:244)
at org.springframework.web.util.WebUtils.getSessionId(WebUtils.java:359)
at org.springframework.web.servlet.FrameworkServlet.publishRequestHandledEvent(FrameworkServlet.java:1145)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1023)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilterInternal(AuthorizationFilter.java:77)
java.lang.RuntimeException: getSession(false)
at example.SessionAccessedFilter$1.getSession(SessionAccessedFilter.java:25)
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:244)
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:244)
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:244)
at org.springframework.web.servlet.support.SessionFlashMapManager.retrieveFlashMaps(SessionFlashMapManager.java:48)
at org.springframework.web.servlet.support.AbstractFlashMapManager.retrieveAndUpdate(AbstractFlashMapManager.java:95)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:948)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilterInternal(AuthorizationFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:351)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
NOTE: We have already done this for WebSession in reactive applications
@rwinch I like to work on this issue, could I?
Thanks @Daniel69! The issue is yours :smile:
This will likely be a larger issue and a bit tricky since a lot of the architecture relies on the assumption that the Authentication
is resolved.
I think we should start by finding the places where the HttpSession is resolved and how we can minimize it's access. I believe this is just at the authorization layer, but may be mistaken.
As for the authorization layer, I think we want to change it to be similar to how the WebFlux authorization APIs are. The API would not require the Authentication
to be resolved up front. We would write an adapter for the new API to support the old model.
@rwinch when you say
The API would not require the Authentication to be resolved up front. We would write an adapter for the new API to support the old model.
You mean that we would resolve the Authentication and therefore the HttpSession in a lazy way ?
I mean that right now the AccessDecisionManager takes the Authentication
as an input. To invoke the decide method, we need to resolve the Authentication
which means we must access the HttpSession
.
To get around this we would need to create an API similar to ReactiveAuthorizationManager which didn't take the Authentication
directly, so looking it up and thus accessing the session could be deferred or not invoked at all in the event that it was permitAll.
Hi. Is there any progress on this one?