But, after setting this, it works. Now, every request does re-authenticate and doesn't use HttpSession
(it seem).
// project a
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity(debug = true)
public class WebSecurityConfig {
@Bean
public SecurityFilterChain docsFilterChain(HttpSecurity http) throws Exception {
return http
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.build();
// project b
public class DummyDsl extends AbstractHttpConfigurer<DummyDsl, HttpSecurity> {
@Override
public void init(HttpSecurity http) throws Exception {
.formLogin(AbstractHttpConfigurer::disable)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
public static DummyDsl dummyDsl() {
return new DummyDsl();
This also seem to work based on what I have tried
I also wanted to try
I wanted to try to setAllowSessionCreation to false (over using NullSecurityContextRepository
), but not quite sure how to define it.
Expected behavior
The expected behavior should always authenticate per request, and the logs I expect to see should be something along
FilterChainProxy: Securing POST /api/v1/....
FilterChainProxy: Invoking DisableEncodeUrlFilter (1/11)
... omitted
FilterChainProxy: Invoking RequestHeaderAuthenticationFilter(6/11)
HttpSessionSecurityContextRepository: No HttpSession currently exists
SupplierDeferredSecurityContext: Created SecurityContextImpl [Null authentication]
SupplierDeferredSecurityContext: Created SecurityContextImpl [Null authentication]
RequestHeaderAuthenticationFilter: Authenticating null
RequestHeaderAuthenticationFilter: preAuthenticatePrincipal = xxxx, trying to authenticate
ProviderManager: Authenticating request with PreAuthenticatedAuthenticationProvider (1/1)
... omitted
Sample
I can try to submit a reproduce if required. I'm hoping that it's a rather straight-forward case of me not understanding enough, or having misconfiguration on my end than it is a bug. Please do let me know if more information is required as well.
Thanks!
@bwgjoseph thanks for the report. However, it's somewhat difficult to tell whether your report is simply a mis-configuration, a misunderstanding, or a bug. The formLogin()
authentication mechanism is designed to work with sessions, so it's not clear how you intended to make this work with "stateless" sessionManagement()
.
For that reason, it feels like this is a question that would be better suited to Stack Overflow. We prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add a minimal sample that reproduces this issue if you feel this is a genuine bug.
Having said that, please see this comment for some context. I'm going to close this issue for now. However, if you can provide a sample that points to an issue with configuring a custom DSL specifically (and not a mis-configuration), we can re-open.
Hi @sjohnr, thanks for the response.
I do believe it is a bug, so I took some time to make the reproduce repo. As I am seeing differing behavior when used (stateless session management) with and without custom dsl.
Also, I'm not sure if I fully understand (as I'm still new to spring-security) what you explained in here, and I do think it might be a different issue.
But I like to say that this has nothing to do with formLogin
. I'm not using formLogin
for anything. My use-case is similar to what was described in the docs, where I want to re-authenticate on every single request without having any session stored.
In my custom dsl, I have the following configuration
public class DummyDsl extends AbstractHttpConfigurer<DummyDsl, HttpSecurity> {
@Override
public void init(HttpSecurity http) throws Exception {
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
public static DummyDsl dummyDsl() {
return new DummyDsl();
public HttpSecurity build() {
return super.getBuilder();
Which is configured in spring.factories
so it will be picked up and applied automatically. So with the following configuration
public class WebSecurityConfig {
@Bean
public SecurityFilterChain apiFilterChain(HttpSecurity http, RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter) throws Exception {
return http
.addFilter(requestHeaderAuthenticationFilter)
.build();
I do expect that the configuration for sessionManagement
will be applied apiFilterChain
. However, from what I have seen, it does not get applied.
Scenario 1
When I run using the above configuration, this is the logs
curl --location 'localhost:8080/me'
--header 'X-User: hello' \
click to view logs
2023-10-01T04:16:59.149+08:00 TRACE 2816 --- [nio-9999-exec-2] o.s.security.web.FilterChainProxy : Invoking LogoutFilter (6/12)
2023-10-01T04:16:59.151+08:00 TRACE 2816 --- [nio-9999-exec-2] o.s.s.w.a.logout.LogoutFilter : Did not match request to Ant [pattern='/logout', POST]
2023-10-01T04:16:59.153+08:00 TRACE 2816 --- [nio-9999-exec-2] o.s.security.web.FilterChainProxy : Invoking RequestHeaderAuthenticationFilter (7/12)
2023-10-01T04:16:59.156+08:00 TRACE 2816 --- [nio-9999-exec-2] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2023-10-01T04:16:59.157+08:00 TRACE 2816 --- [nio-9999-exec-2] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
2023-10-01T04:16:59.157+08:00 TRACE 2816 --- [nio-9999-exec-2] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
2023-10-01T04:16:59.158+08:00 DEBUG 2816 --- [nio-9999-exec-2] .w.a.p.RequestHeaderAuthenticationFilter : Authenticating null
2023-10-01T04:16:59.167+08:00 DEBUG 2816 --- [nio-9999-exec-2] .w.a.p.RequestHeaderAuthenticationFilter : preAuthenticatedPrincipal = hello, trying to authenticate
2023-10-01T04:16:59.173+08:00 TRACE 2816 --- [nio-9999-exec-2] o.s.s.authentication.ProviderManager : Authenticating request with MyPreAuthenticationProvider (1/1)
2023-10-01T04:16:59.185+08:00 DEBUG 2816 --- [nio-9999-exec-2] .w.a.p.RequestHeaderAuthenticationFilter : Authentication success: PreAuthenticatedAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=bwgjoseph, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[RW]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[RW]]
2023-10-01T04:16:59.334+08:00 WARN 2816 --- [nio-9999-exec-2] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [128] milliseconds.
2023-10-01T04:16:59.338+08:00 INFO 2816 --- [nio-9999-exec-2] Spring Security Debugger :
************************************************************
New HTTP session created: 4A6F1D62CC3544616E31A973EBB17B45
Call stack:
// omitted
2023-10-01T04:16:59.352+08:00 DEBUG 2816 --- [nio-9999-exec-2] w.c.HttpSessionSecurityContextRepository : Stored SecurityContextImpl [Authentication=PreAuthenticatedAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=bwgjoseph, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[RW]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[RW]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@252dff08]
2023-10-01T04:16:59.357+08:00 TRACE 2816 --- [nio-9999-exec-2] o.s.security.web.FilterChainProxy : Invoking RequestCacheAwareFilter (8/12)
// omitted
It's the first time running, so it is attempting authentication, then it stores into SecurityContextImpl
If I were to run the same request again
// omitted
2023-10-01T04:19:41.185+08:00 TRACE 2816 --- [nio-9999-exec-6] o.s.security.web.FilterChainProxy : Invoking LogoutFilter (6/12)
2023-10-01T04:19:41.195+08:00 TRACE 2816 --- [nio-9999-exec-6] o.s.s.w.a.logout.LogoutFilter : Did not match request to Ant [pattern='/logout', POST]
2023-10-01T04:19:41.205+08:00 TRACE 2816 --- [nio-9999-exec-6] o.s.security.web.FilterChainProxy : Invoking RequestHeaderAuthenticationFilter (7/12)
2023-10-01T04:19:41.209+08:00 TRACE 2816 --- [nio-9999-exec-6] w.c.HttpSessionSecurityContextRepository : Retrieved SecurityContextImpl [Authentication=PreAuthenticatedAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=bwgjoseph, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[RW]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[RW]]] from SPRING_SECURITY_CONTEXT
2023-10-01T04:19:41.211+08:00 TRACE 2816 --- [nio-9999-exec-6] .w.a.p.RequestHeaderAuthenticationFilter : Did not authenticate since request did not match [org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter$PreAuthenticatedProcessingRequestMatcher@4909428]
2023-10-01T04:19:41.212+08:00 TRACE 2816 --- [nio-9999-exec-6] o.s.security.web.FilterChainProxy : Invoking RequestCacheAwareFilter (8/12)
2023-10-01T04:19:41.218+08:00 TRACE 2816 --- [nio-9999-exec-6] o.s.s.w.s.HttpSessionRequestCache : matchingRequestParameterName is required for getMatchingRequest to lookup a value, but not provided
2023-10-01T04:19:41.246+08:00 TRACE 2816 --- [nio-9999-exec-6] o.s.security.web.FilterChainProxy : Invoking SecurityContextHolderAwareRequestFilter (9/12)
// omitted
Can see that it's not authenticating again, but retrieved from the context.
Scenario 2
The only delta here is that I am also configuring the sessionManagement
directly in apiFilterChain
(on top of what was already configured in dummyDsl)
public class WebSecurityConfig {
@Bean
public SecurityFilterChain apiFilterChain(HttpSecurity http, RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter) throws Exception {
return http
.addFilter(requestHeaderAuthenticationFilter)
// i'm expecting that i should not need to add this line as it is configured in custom dsl
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.build();
With the above configuration, I ran the same http call
click to view logs
2023-10-01T04:23:26.318+08:00 TRACE 18288 --- [nio-9999-exec-2] o.s.security.web.FilterChainProxy : Invoking LogoutFilter (6/12)
2023-10-01T04:23:26.318+08:00 TRACE 18288 --- [nio-9999-exec-2] o.s.s.w.a.logout.LogoutFilter : Did not match request to Ant [pattern='/logout', POST]
2023-10-01T04:23:26.319+08:00 TRACE 18288 --- [nio-9999-exec-2] o.s.security.web.FilterChainProxy : Invoking RequestHeaderAuthenticationFilter (7/12)
2023-10-01T04:23:26.320+08:00 TRACE 18288 --- [nio-9999-exec-2] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
2023-10-01T04:23:26.321+08:00 DEBUG 18288 --- [nio-9999-exec-2] .w.a.p.RequestHeaderAuthenticationFilter : Authenticating null
2023-10-01T04:23:26.321+08:00 DEBUG 18288 --- [nio-9999-exec-2] .w.a.p.RequestHeaderAuthenticationFilter : preAuthenticatedPrincipal = hello, trying to authenticate
2023-10-01T04:23:26.323+08:00 TRACE 18288 --- [nio-9999-exec-2] o.s.s.authentication.ProviderManager : Authenticating request with MyPreAuthenticationProvider (1/1)
2023-10-01T04:23:26.325+08:00 DEBUG 18288 --- [nio-9999-exec-2] .w.a.p.RequestHeaderAuthenticationFilter : Authentication success: PreAuthenticatedAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=bwgjoseph, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[RW]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[RW]]
2023-10-01T04:23:26.554+08:00 WARN 18288 --- [nio-9999-exec-2] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [218] milliseconds.
2023-10-01T04:23:26.559+08:00 INFO 18288 --- [nio-9999-exec-2] Spring Security Debugger :
************************************************************
New HTTP session created: 88E2161FD4E90002135A8B0F1C2E5897
Call stack:
// omitted
2023-10-01T04:23:26.575+08:00 DEBUG 18288 --- [nio-9999-exec-2] w.c.HttpSessionSecurityContextRepository : Stored SecurityContextImpl [Authentication=PreAuthenticatedAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=bwgjoseph, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[RW]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[RW]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@78062cf4]
2023-10-01T04:23:26.585+08:00 TRACE 18288 --- [nio-9999-exec-2] o.s.security.web.FilterChainProxy : Invoking RequestCacheAwareFilter (8/12)
2023-10-01T04:23:26.586+08:00 TRACE 18288 --- [nio-9999-exec-2] o.s.security.web.FilterChainProxy : Invoking SecurityContextHolderAwareRequestFilter (9/12)
2023-10-01T04:23:26.589+08:00 TRACE 18288 --- [nio-9999-exec-2] o.s.security.web.FilterChainProxy : Invoking AnonymousAuthenticationFilter (10/12)
// omitted
So this authenticates, and also stores into context which seem correct to me
But, if I were to run the http call again. It will attempt to authenticate again, instead of retrieving from the store.
2023-10-01T04:24:35.685+08:00 TRACE 18288 --- [nio-9999-exec-5] o.s.security.web.FilterChainProxy : Invoking LogoutFilter (6/12)
2023-10-01T04:24:35.685+08:00 TRACE 18288 --- [nio-9999-exec-5] o.s.s.w.a.logout.LogoutFilter : Did not match request to Ant [pattern='/logout', POST]
2023-10-01T04:24:35.685+08:00 TRACE 18288 --- [nio-9999-exec-5] o.s.security.web.FilterChainProxy : Invoking RequestHeaderAuthenticationFilter (7/12)
2023-10-01T04:24:35.686+08:00 TRACE 18288 --- [nio-9999-exec-5] .s.s.w.c.SupplierDeferredSecurityContext : Created SecurityContextImpl [Null authentication]
2023-10-01T04:24:35.687+08:00 DEBUG 18288 --- [nio-9999-exec-5] .w.a.p.RequestHeaderAuthenticationFilter : Authenticating null
2023-10-01T04:24:35.687+08:00 DEBUG 18288 --- [nio-9999-exec-5] .w.a.p.RequestHeaderAuthenticationFilter : preAuthenticatedPrincipal = hello, trying to authenticate
2023-10-01T04:24:35.724+08:00 TRACE 18288 --- [nio-9999-exec-5] o.s.s.authentication.ProviderManager : Authenticating request with MyPreAuthenticationProvider (1/1)
2023-10-01T04:24:35.733+08:00 DEBUG 18288 --- [nio-9999-exec-5] .w.a.p.RequestHeaderAuthenticationFilter : Authentication success: PreAuthenticatedAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=bwgjoseph, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[RW]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=88E2161FD4E90002135A8B0F1C2E5897], Granted Authorities=[RW]]
2023-10-01T04:24:35.735+08:00 DEBUG 18288 --- [nio-9999-exec-5] w.c.HttpSessionSecurityContextRepository : Stored SecurityContextImpl [Authentication=PreAuthenticatedAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=bwgjoseph, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[RW]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=88E2161FD4E90002135A8B0F1C2E5897], Granted Authorities=[RW]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@78062cf4]
2023-10-01T04:24:35.752+08:00 TRACE 18288 --- [nio-9999-exec-5] o.s.security.web.FilterChainProxy : Invoking RequestCacheAwareFilter (8/12)
2023-10-01T04:24:35.767+08:00 TRACE 18288 --- [nio-9999-exec-5] o.s.security.web.FilterChainProxy : Invoking SecurityContextHolderAwareRequestFilter (9/12)
2023-10-01T04:24:35.781+08:00 TRACE 18288 --- [nio-9999-exec-5] o.s.security.web.FilterChainProxy : Invoking AnonymousAuthenticationFilter (10/12)
2023-10-01T04:24:35.782+08:00 TRACE 18288 --- [nio-9999-exec-5] o.s.security.web.FilterChainProxy : Invoking SessionManagementFilter (11/12)
// omitted
Again, this could be my limited understading on spring-security. So do point out if I am missing something obvious. Am also happy to provide more information / clarification if necessary.
Thank you for looking into this!
update: wanted to add on this
Based on the session-management-docs, it states that using stateless
will configure to use NullSecurityContextRepository
but given what I've wrote above, and my observation, I had to manually define securityContext
in my custom dsl.
public class DummyDsl extends AbstractHttpConfigurer<DummyDsl, HttpSecurity> {
@Override
public void init(HttpSecurity http) throws Exception {
.securityContext(context -> context.securityContextRepository(new NullSecurityContextRepository));
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
// omitted
If I define .securityContext
, then there is no need for me to define .sessionManagement
in my apiFilterChain
@bwgjoseph thanks for following up with the sample.
I have reviewed your sample, and I do see that the behavior is slightly different when applying the DummyDsl
via spring.factories
vs applying it directly in the apiFilterChain()
. So I understand why this is confusing, and in fact I haven't dug deeply yet to be able to accurately explain the difference in behavior so I agree it's odd. I think that it has to do with the order in which things are configured. It most likely relates to framework internals around the use of http.setSharedObject(...)
in SessionManagementConfigurer
in the DSL. It could be that you've found a bug, but I don't yet see any bug here.
The reason it's difficult to spot any obvious bugs in that your configuration and expectations around session management seem incorrect, and don't take into account what I discussed in the linked comment:
First, each authentication filter is now configured with a SecurityContextRepository and is responsible for persisting the SecurityContext itself, making the SessionManagementFilter unnecessary.
Second, the behavior in 5.8 was to register SessionManagementFilter by default, with SessionCreationPolicy.STATELESS configuring things to avoid creating a session. In 6.x, a SessionManagementFilter is no longer registered by default. However, choosing SessionCreationPolicy.STATELESS does register one again.
In the case of RequestHeaderAuthenticationFilter
, you need to call setSecurityContextRepository()
yourself, since you are not using the DSL to configure it. (Indeed, it is not configurable via the DSL.) In addition, I would expect you to stop calling sessionManagement()
in 6.x, and instead rely on the SecurityContextRepository
you configured, which means your custom DSL is not necessary (or at least should be changed, but since you haven't explained your use case I can't predict how it should change).
My best guess as to what you should be doing instead is:
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity(debug = true)
public class WebSecurityConfig {
@Bean
public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
// Authorization is added to make it clear what's intended by this filter chain
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
// Authentication is configured via DummyDsl which is registered via spring.factories
return http.build();
public class DummyDsl extends AbstractHttpConfigurer<DummyDsl, HttpSecurity> {
@Override
public void configure(HttpSecurity http) throws Exception {
RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter =
new RequestHeaderAuthenticationFilter();
requestHeaderAuthenticationFilter.setPrincipalRequestHeader("X-User");
requestHeaderAuthenticationFilter.setExceptionIfHeaderMissing(true);
AuthenticationManager authenticationManager =
new ProviderManager(new MyPreAuthenticationProvider());
requestHeaderAuthenticationFilter.setAuthenticationManager(authenticationManager);
RequestAttributeSecurityContextRepository securityContextRepository =
new RequestAttributeSecurityContextRepository();
requestHeaderAuthenticationFilter.setSecurityContextRepository(securityContextRepository);
http.addFilter(requestHeaderAuthenticationFilter);
// ...
This configuration is simpler, avoids use of sessionManagement()
in 6.x, does not create any sessions nor load anything from a session, and still makes use of the custom DSL. For now, I'm going to leave this issue closed, and I hope that the above explanation helps you. If you have further questions, please open a stackoverflow question and share the link.
One final note: As I mentioned in the other issue, I do believe updates to the documentation are needed here, so that ticket will remain open.
Thanks for the explanation, I think I'm having a better idea w.r.t SecurityContextRepository
now.
I went into AbstractPreAuthenticatedProcessingFilter
class, and see that the default is HttpSessionSecurityContextRepository
which according to the docs, it means it stores the security context in the HttpSession between requests. And I think I do get why I should switch to RequestAttributeSecurityContextRepository
because I don't want to save the session between request but I don't quite get why the default is set to HttpSessionSecurityContextRepository
? Shouldn't PreAuthenticated
requests always be "re-evaluated"? And since that HttpSessionSecurityContextRepository
is the default, when I make any API request, it will always throw this exception
023-10-04T00:50:00.282+08:00 TRACE 7204 --- [nio-9999-exec-1] o.s.s.authentication.ProviderManager : Authenticating request with MyPreAuthenticationProvider (1/1)
2023-10-04T00:50:00.285+08:00 DEBUG 7204 --- [nio-9999-exec-1] .w.a.p.RequestHeaderAuthenticationFilter : Authentication success: PreAuthenticatedAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=bwgjoseph, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[RW]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=null], Granted Authorities=[RW]]
2023-10-04T00:50:00.438+08:00 WARN 7204 --- [nio-9999-exec-1] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [140] milliseconds.
2023-10-04T00:50:00.468+08:00 INFO 7204 --- [nio-9999-exec-1] Spring Security Debugger :
************************************************************
New HTTP session created: EC039CCFFC3DBF8EBADEE88F08B08ECA
Call stack:
at org.springframework.security.web.debug.Logger.info(Logger.java:46)
at org.springframework.security.web.debug.DebugFilter$DebugRequestWrapper.getSession(DebugFilter.java:171)
at org.springframework.security.web.debug.DebugFilter$DebugRequestWrapper.getSession(DebugFilter.java:181)
at jakarta.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:221)
at jakarta.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:221)
at org.springframework.security.web.context.HttpSessionSecurityContextRepository.saveContextInHttpSession(HttpSessionSecurityContextRepository.java:169)
at org.springframework.security.web.context.HttpSessionSecurityContextRepository.saveContext(HttpSessionSecurityContextRepository.java:152)
at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.successfulAuthentication(AbstractPreAuthenticatedProcessingFilter.java:221)
at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doAuthenticate(AbstractPreAuthenticatedProcessingFilter.java:201)
at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doFilter(AbstractPreAuthenticatedProcessingFilter.java:142)
// omitted
2023-10-04T00:50:00.478+08:00 DEBUG 7204 --- [nio-9999-exec-1] w.c.HttpSessionSecurityContextRepository : Stored SecurityContextImpl [Authentication=PreAuthenticatedAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=bwgjoseph, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[RW]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=null], Granted Authorities=[RW]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@2368adaa]
2023-10-04T00:50:00.481+08:00 TRACE 7204 --- [nio-9999-exec-1] o.s.security.web.FilterChainProxy : Invoking RequestCacheAwareFilter (8/11)
Is this expected?
This configuration is simpler, avoids use of sessionManagement() in 6.x, does not create any sessions nor load anything from a session, and still makes use of the custom DSL
Thanks for showing this, and I do agree that this configuration is better. However, for my case, I'm not sure if the correct approach is to make custom dsl configurable from the consumer (like provide the class to custom dsl)
For example, my RequestHeaderAuthenticationFilter
is actually taking in AuthenticationManager
and AuthenticationDetailsSource
bean which I do have a default beans declared, but it can be overwritten by consumer of the library.
I'm trying to write a common library that can be re-use across projects
// example
@Bean
@ConditionalOnMissingBean
public AuthenticationManager authenticationManager(AuthenticationProvider authenticationProvider) {
return new ProviderManager(authenticationProvider);
@Bean
public RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter(AuthenticationManager authenticationManager, AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter = new RequestHeaderAuthenticationFilter();
requestHeaderAuthenticationFilter.setPrincipalRequestHeader("X-User");
requestHeaderAuthenticationFilter.setExceptionIfHeaderMissing(true);
requestHeaderAuthenticationFilter.setAuthenticationManager(authenticationManager);
requestHeaderAuthenticationFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
RequestAttributeSecurityContextRepository securityContextRepository =
new RequestAttributeSecurityContextRepository();
requestHeaderAuthenticationFilter.setSecurityContextRepository(securityContextRepository);
return requestHeaderAuthenticationFilter;
In this case, if I were to define RequestHeaderAuthenticationFilter
within the custom dsl
, then that would mean that it can only be configured something like this?
public class DummyDsl extends AbstractHttpConfigurer<DummyDsl, HttpSecurity> {
@Override
public void init(HttpSecurity http) throws Exception {
http.formLogin(AbstractHttpConfigurer::disable);
// so is it ok to use this way to grab the correct bean, to set to authenticationManager?
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
AuthenticationManager authenticationManager = context.getBean(AuthenticationManager.class);
// actually i'm not sure how to grab generic type of bean from context correctly
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = context.getBean(AuthenticationDetailsSource.class);
RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter = new RequestHeaderAuthenticationFilter();
requestHeaderAuthenticationFilter.setPrincipalRequestHeader("X-User");
requestHeaderAuthenticationFilter.setExceptionIfHeaderMissing(true);
requestHeaderAuthenticationFilter.setAuthenticationManager(authenticationManager);
requestHeaderAuthenticationFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
RequestAttributeSecurityContextRepository securityContextRepository =
new RequestAttributeSecurityContextRepository();
requestHeaderAuthenticationFilter.setSecurityContextRepository(securityContextRepository);
// omitted
public class WebSecurityConfig {
@Bean
public SecurityFilterChain apiFilterChain(HttpSecurity http, RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter) throws Exception {
return http
// Authorization is added to make it clear what's intended by this filter chain
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
.build();
// omitted
This way, I'm still allowing users to create their own AuthenticationManager
and AuthenticationDetailsSource
bean, which will be picked up in custom dsl through http.getSharedObject(ApplicationContext.class)
which then get passed to RequestHeaderAuthenticationFilter
. This makes it such that there's no need to manually add .addFilter(requestHeaderAuthenticationFilter)
in each of the SecurityFilterChain
, right?
It could be that you've found a bug, but I don't yet see any bug here.
You mentioned this, but from my perspective, if the behavior differs, wouldn't it be considered as bug, or rather requires deeper investigation (as you have pointed out it could be http.setSharedObject(...)
)?
Hope I'm not making it more confusing, and thanks for your patience!
It could be that you've found a bug, but I don't yet see any bug here.
You mentioned this, but from my perspective, if the behavior differs, wouldn't it be considered as bug, or rather requires deeper investigation (as you have pointed out it could be http.setSharedObject(...)
)?
If you believe you have found a bug (I currently do not), please provide a minimal sample that reproduces it. In this case, I would suggest removing anything with custom authentication, and then point to what is broken when you use the filter chain bean vs the custom DSL.
Regarding all other questions, please go to stackoverflow for this. I am happy to answer questions, but this is not the place for that as I have mentioned already.
I just ran another round of testing, and it does seem that it is a lack of understanding on my end, rather than a bug as suspected initially.
Just to close it off, and hope that I got it right. It seems like the misunderstanding here (or cause of confusion) is the usage of RequestHeaderAuthenticationFilter
which register HttpSessionSecurityContextRepository
by default that results in storing HttpSession
between requests as opposed to using RequestAttributeSecurityContextRepository
that does not.