Add Explicit SessionAuthenticationStrategy Option

SessionAuthenticationFilter requires accessing the HttpSession to do its
job. Previously, there was no way to just disable the
SessionAuthenticationFilter despite the fact that
SessionAuthenticationStrategy is invoked by the authentication filters
directly.

This commit adds an option to disable SessionManagmentFilter in favor of
requiring explicit SessionAuthenticationStrategy invocation already
performed by the authentication filters.

Closes gh-11455
This commit is contained in:
Rob Winch 2022-08-17 15:20:07 -05:00
parent 51dc672625
commit 89f8310d6c
5 changed files with 59 additions and 15 deletions

View File

@ -135,6 +135,8 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
private AuthenticationFailureHandler sessionAuthenticationFailureHandler;
private boolean requireExplicitAuthenticationStrategy;
/**
* Creates a new instance
* @see HttpSecurity#sessionManagement()
@ -155,6 +157,19 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
return this;
}
/**
* Setting this means that explicit invocation of
* {@link SessionAuthenticationStrategy} is required.
* @param requireExplicitAuthenticationStrategy require explicit invocation of
* {@link SessionAuthenticationStrategy}
* @return the {@link SessionManagementConfigurer} for further customization
*/
public SessionManagementConfigurer<H> requireExplicitAuthenticationStrategy(
boolean requireExplicitAuthenticationStrategy) {
this.requireExplicitAuthenticationStrategy = requireExplicitAuthenticationStrategy;
return this;
}
/**
* Setting this attribute will inject the provided invalidSessionStrategy into the
* {@link SessionManagementFilter}. When an invalid session ID is submitted, the
@ -351,6 +366,28 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
@Override
public void configure(H http) {
SessionManagementFilter sessionManagementFilter = createSessionManagementFilter(http);
if (sessionManagementFilter != null) {
http.addFilter(sessionManagementFilter);
}
if (isConcurrentSessionControlEnabled()) {
ConcurrentSessionFilter concurrentSessionFilter = createConcurrencyFilter(http);
concurrentSessionFilter = postProcess(concurrentSessionFilter);
http.addFilter(concurrentSessionFilter);
}
if (!this.enableSessionUrlRewriting) {
http.addFilter(new DisableEncodeUrlFilter());
}
if (this.sessionPolicy == SessionCreationPolicy.ALWAYS) {
http.addFilter(new ForceEagerSessionCreationFilter());
}
}
private SessionManagementFilter createSessionManagementFilter(H http) {
if (this.requireExplicitAuthenticationStrategy) {
return null;
}
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(securityContextRepository,
getSessionAuthenticationStrategy(http));
@ -371,20 +408,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
sessionManagementFilter.setTrustResolver(trustResolver);
}
sessionManagementFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
sessionManagementFilter = postProcess(sessionManagementFilter);
http.addFilter(sessionManagementFilter);
if (isConcurrentSessionControlEnabled()) {
ConcurrentSessionFilter concurrentSessionFilter = createConcurrencyFilter(http);
concurrentSessionFilter = postProcess(concurrentSessionFilter);
http.addFilter(concurrentSessionFilter);
}
if (!this.enableSessionUrlRewriting) {
http.addFilter(new DisableEncodeUrlFilter());
}
if (this.sessionPolicy == SessionCreationPolicy.ALWAYS) {
http.addFilter(new ForceEagerSessionCreationFilter());
}
return postProcess(sessionManagementFilter);
}
private ConcurrentSessionFilter createConcurrencyFilter(H http) {

View File

@ -103,6 +103,8 @@ class HttpConfigurationBuilder {
private static final String OPT_CHANGE_SESSION_ID = "changeSessionId";
private static final String ATT_AUTHENTICATION_STRATEGY_EXPLICIT_INVOCATION = "authentication-strategy-explicit-invocation";
private static final String ATT_INVALID_SESSION_URL = "invalid-session-url";
private static final String ATT_SESSION_AUTH_STRATEGY_REF = "session-authentication-strategy-ref";
@ -538,7 +540,11 @@ class HttpConfigurationBuilder {
sessionMgmtFilter.addPropertyReference("invalidSessionStrategy", invalidSessionStrategyRef);
}
sessionMgmtFilter.addConstructorArgReference(sessionAuthStratRef);
this.sfpf = (RootBeanDefinition) sessionMgmtFilter.getBeanDefinition();
boolean registerSessionMgmtFilter = (sessionMgmtElt == null
|| !"true".equals(sessionMgmtElt.getAttribute(ATT_AUTHENTICATION_STRATEGY_EXPLICIT_INVOCATION)));
if (registerSessionMgmtFilter) {
this.sfpf = (RootBeanDefinition) sessionMgmtFilter.getBeanDefinition();
}
this.sessionStrategyRef = new RuntimeBeanReference(sessionAuthStratRef);
}

View File

@ -917,6 +917,9 @@ session-management =
## Session-management related functionality is implemented by the addition of a SessionManagementFilter to the filter stack.
element session-management {session-management.attlist, concurrency-control?}
session-management.attlist &=
## Specifies that SessionAuthenticationStrategy must be explicitly invoked. Default false (i.e. SessionManagementFilter will implicitly invoke SessionAuthenticationStrategy).
attribute authentication-strategy-explicit-invocation {xsd:boolean}?
session-management.attlist &=
## Indicates how session fixation protection will be applied when a user authenticates. If set to "none", no protection will be applied. "newSession" will create a new empty session, with only Spring Security-related attributes migrated. "migrateSession" will create a new session and copy all session attributes to the new session. In Servlet 3.1 (Java EE 7) and newer containers, specifying "changeSessionId" will keep the existing session and use the container-supplied session fixation protection (HttpServletRequest#changeSessionId()). Defaults to "changeSessionId" in Servlet 3.1 and newer containers, "migrateSession" in older containers. Throws an exception if "changeSessionId" is used in older containers.
attribute session-fixation-protection {"none" | "newSession" | "migrateSession" | "changeSessionId" }?

View File

@ -2662,6 +2662,13 @@
</xs:attributeGroup>
<xs:attributeGroup name="session-management.attlist">
<xs:attribute name="authentication-strategy-explicit-invocation" type="xs:boolean">
<xs:annotation>
<xs:documentation>Specifies that SessionAuthenticationStrategy must be explicitly invoked. Default false
(i.e. SessionManagementFilter will implicitly invoke SessionAuthenticationStrategy).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="session-fixation-protection">
<xs:annotation>
<xs:documentation>Indicates how session fixation protection will be applied when a user authenticates. If

View File

@ -2243,6 +2243,10 @@ Session-management related functionality is implemented by the addition of a `Se
=== <session-management> Attributes
[[nsa-session-management-authentication-strategy-explicit-invocation]]
* **authentication-strategy-explicit-invocation**
Setting this attribute to true will mean that `SessionManagementFilter` will not be injected and explicit invocation of SessionAuthenticationStrategy is required.
[[nsa-session-management-invalid-session-url]]
* **invalid-session-url**
Setting this attribute will inject the `SessionManagementFilter` with a `SimpleRedirectInvalidSessionStrategy` configured with the attribute value.