经过 SAML 身份验证的用户不会出现在 Spring 安全的 SessionRegistry 中
SAML authenticated users don't appear in Spring Security's SessionRegistry
我们的应用程序过去只有一种登录方式:用户名和密码。一旦新用户登录到应用程序,他们的会话将出现在 Spring 安全的 SessionRegistry
.
中
现在我正在 Spring SAML 的帮助下实现 SAML 支持。我将设置主要面向 sample application's configuration。一切正常。但是我注意到通过 SAML 登录的用户不会将他们的会话添加到 SessionRegistry
.
基于表单的身份验证的常用上下文文件包含以下内容:
<session-management
invalid-session-url="/login"
session-fixation-protection="newSession"
session-authentication-error-url="/login?invalid_session=1">
<concurrency-control
max-sessions="1"
error-if-maximum-exceeded="false"
session-registry-alias="springSessionRegistry"/>
</session-management>
在我的 SAML 配置的 http
元素中,我添加了相同的内容。这创建了一个新的 SessionRegistry
但它不包含任何内容。我也试过了
<concurrency-control session-registry-ref="springSessionRegistry"/>
但这也不包含任何经过 SAML 身份验证的会话。
那么如何访问 SAML 会话?
问题是 Spring Security 的 bean 定义解析器只会自动 link 基于 session-management
和 concurrency-control
创建的 beans 到核心 Spring 安全模块。这意味着 SAMLProcessingFilter.setSessionAuthenticationStrategy()
没有被调用。
您应该能够通过以下方式声明 samlWebSSOProcessingFilter
bean(它指的是 concurrency-control
元素自动创建的并发 bean)使其工作:
<bean id="samlWebSSOProcessingFilter" class="org.springframework.security.saml.SAMLProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="successRedirectHandler"/>
<property name="authenticationFailureHandler" ref="failureRedirectHandler"/>
<property name="sessionAuthenticationStrategy" ref="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy#0"/>
</bean>
正如我在评论 Vladimir 的回答时所说,我的问题是我只向 samlWebSSOProcessingFilter 添加了一个 ConcurrentSessionControlAuthenticationStrategy,因此,新登录的用户没有在 Spring 的 SessionRegistry 中注册安全。
为了解决这个问题,我创建了一个 CompositeSessionAuthenticationStrategy,如下所示:
@Bean
public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception {
SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager());
samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
samlWebSSOProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
samlWebSSOProcessingFilter.setSessionAuthenticationStrategy(authStrategy());
return samlWebSSOProcessingFilter;
}
/**
* @return the strategy for the SAML authentication: ConcurrentSessionControl (max 1 session per user)
* + RegisterSessionAuthStrat (otherwise, the session of the users are not tracked when they authenticate with SAML)
*
* @author Cyril Gambis
* @date 27 juil. 2020
*/
private CompositeSessionAuthenticationStrategy authStrategy() {
List<SessionAuthenticationStrategy> strategies = new ArrayList<>();
ConcurrentSessionControlAuthenticationStrategy concurrentStrategy = new ConcurrentSessionControlAuthenticationStrategy(this.sessionRegistry);
concurrentStrategy.setExceptionIfMaximumExceeded(false);
RegisterSessionAuthenticationStrategy registerStrategy = new RegisterSessionAuthenticationStrategy(this.sessionRegistry);
strategies.add(concurrentStrategy);
strategies.add(registerStrategy);
CompositeSessionAuthenticationStrategy compositeStrategy = new CompositeSessionAuthenticationStrategy(strategies);
return compositeStrategy;
}
现在,新用户已经正确注册了。
我们的应用程序过去只有一种登录方式:用户名和密码。一旦新用户登录到应用程序,他们的会话将出现在 Spring 安全的 SessionRegistry
.
现在我正在 Spring SAML 的帮助下实现 SAML 支持。我将设置主要面向 sample application's configuration。一切正常。但是我注意到通过 SAML 登录的用户不会将他们的会话添加到 SessionRegistry
.
基于表单的身份验证的常用上下文文件包含以下内容:
<session-management
invalid-session-url="/login"
session-fixation-protection="newSession"
session-authentication-error-url="/login?invalid_session=1">
<concurrency-control
max-sessions="1"
error-if-maximum-exceeded="false"
session-registry-alias="springSessionRegistry"/>
</session-management>
在我的 SAML 配置的 http
元素中,我添加了相同的内容。这创建了一个新的 SessionRegistry
但它不包含任何内容。我也试过了
<concurrency-control session-registry-ref="springSessionRegistry"/>
但这也不包含任何经过 SAML 身份验证的会话。
那么如何访问 SAML 会话?
问题是 Spring Security 的 bean 定义解析器只会自动 link 基于 session-management
和 concurrency-control
创建的 beans 到核心 Spring 安全模块。这意味着 SAMLProcessingFilter.setSessionAuthenticationStrategy()
没有被调用。
您应该能够通过以下方式声明 samlWebSSOProcessingFilter
bean(它指的是 concurrency-control
元素自动创建的并发 bean)使其工作:
<bean id="samlWebSSOProcessingFilter" class="org.springframework.security.saml.SAMLProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="successRedirectHandler"/>
<property name="authenticationFailureHandler" ref="failureRedirectHandler"/>
<property name="sessionAuthenticationStrategy" ref="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy#0"/>
</bean>
正如我在评论 Vladimir 的回答时所说,我的问题是我只向 samlWebSSOProcessingFilter 添加了一个 ConcurrentSessionControlAuthenticationStrategy,因此,新登录的用户没有在 Spring 的 SessionRegistry 中注册安全。
为了解决这个问题,我创建了一个 CompositeSessionAuthenticationStrategy,如下所示:
@Bean
public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception {
SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager());
samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
samlWebSSOProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
samlWebSSOProcessingFilter.setSessionAuthenticationStrategy(authStrategy());
return samlWebSSOProcessingFilter;
}
/**
* @return the strategy for the SAML authentication: ConcurrentSessionControl (max 1 session per user)
* + RegisterSessionAuthStrat (otherwise, the session of the users are not tracked when they authenticate with SAML)
*
* @author Cyril Gambis
* @date 27 juil. 2020
*/
private CompositeSessionAuthenticationStrategy authStrategy() {
List<SessionAuthenticationStrategy> strategies = new ArrayList<>();
ConcurrentSessionControlAuthenticationStrategy concurrentStrategy = new ConcurrentSessionControlAuthenticationStrategy(this.sessionRegistry);
concurrentStrategy.setExceptionIfMaximumExceeded(false);
RegisterSessionAuthenticationStrategy registerStrategy = new RegisterSessionAuthenticationStrategy(this.sessionRegistry);
strategies.add(concurrentStrategy);
strategies.add(registerStrategy);
CompositeSessionAuthenticationStrategy compositeStrategy = new CompositeSessionAuthenticationStrategy(strategies);
return compositeStrategy;
}
现在,新用户已经正确注册了。