使用 Spring Security Saml 和 SP 应用程序的无状态会话

Posted

技术标签:

【中文标题】使用 Spring Security Saml 和 SP 应用程序的无状态会话【英文标题】:Stateless Sessions with Spring Security Saml and SP Application 【发布时间】:2016-10-30 08:28:34 【问题描述】:

我尝试运行启动示例 spring security saml boot, https://github.com/vdenotaris/spring-boot-security-saml-sample

我能够运行它并与身份提供者集成。

但是,我看到每次都会创建一个会话,并且在用户退出之前一直保持不变。

我在 Spring Boot 中使用基于资源的服务,因此不想要会话的开销。

我尝试在配置方法中添加以下行, http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

但是,使用此设置时,我总是被要求登录身份提供者。

如果我登录,它会返回页面,要求我再次循环登录。

我不确定这是否是禁用会话时的正确行为。

谁能为我提供正确的方法来使用带有 spring security saml 扩展和服务提供程序应用程序的无状态会话。

谢谢,

斯里

【问题讨论】:

【参考方案1】:

对于 SAML 身份验证部分,您肯定需要一个会话,因此您有 2 个选项:

1) 在您的应用程序中有两种不同的安全上下文,一种用于 SAML 身份验证,一种用于无状态服务。不确定您将如何验证您的服务,但它必须具有某种令牌身份验证才能使其成为无状态的。 您可以定义 2 个WebSecurityConfigurerAdapter 并覆盖configure(HttpSecurity http) 方法。然后在 saml 配置中使用http.requestMatchers("/saml/**"),在您的服务配置中使用http.requestMatchers("/service/**")/saml 下的所有内容都将通过 saml 身份验证,/service 下的所有内容都将通过您拥有的任何其他内容。

2) 向 SAML 配置添加更多过滤器(在 saml 过滤器之前),以便它与不同类型的身份验证(例如基于令牌)一起使用,并且只要此过滤器可以生成有效的Authentication 在 saml 过滤器之前你应该很好。

您还可以查看此库:https://github.com/ulisesbocchio/spring-boot-security-saml 以简化您的 SAML 配置

【讨论】:

嗨,Sri,我们的项目有同样的要求。你能告诉我你是如何实现它的吗?提前致谢。小猫 嗨 Sam,我已经尝试过您建议的相同方式,在 saml 身份验证之后,当用户使用不同的端点进行下一次调用时,spring 允许它到达端点。但是第二个端点是无状态的,我创建了一个过滤器并使用不同的逻辑使其验证成功。过滤器中使用的逻辑现在没有用了,因为 spring 认为它已经过身份验证。为了在其余端点实现 (/saml/**) 中解决这个问题,我使会话无效。但我觉得这不是正确的方法。请告诉我是否有更好的解决方案。 -小猫 我认为 1) 尚不清楚的是如何阻止 spring 使用它在 SAML 身份验证期间创建的 jsessionid 在"/service/**" 下使用,似乎 spring 看到 jsessionid 并假设请求已通过身份验证适用于所有地方。 在一天结束时,spring security 只是为每个执行的请求添加了一个过滤器链,其中一个是会话过滤器。您可以修改链并插入您自己的条件会话过滤器或具有不同的“领域”,这些“领域”基本上是针对不同路径的不同过滤器链,您可以使用 WebSecurityConfigurerAdapter 定义它们【参考方案2】:

要在无状态下启用 SAML,您需要:

将 SAMLMessageStorageFactory 设置为空。 确保 SAML 过滤器位于您的记住我过滤器之后。 实际上启用无状态并像往常一样配置您的记住我服务。

请注意,这样做意味着您没有 JSESSIONID,这意味着 spring 将不再记录原始请求的 URL,因此无法处理稍后将您重定向回该 URL。 (建议稍后解决此问题)。

@Configuration
@EnableWebSecurity
public class YourSecurityConfig extends WebSecurityConfigurerAdapter 
    
    /**
     * Since SAML is being used under a stateless mode, we can not use the default
     * Message Storage factory as it uses http sessions. Instead we have to use
     * the EmptyStorageFactory().
     * 
     */
    @Bean
    public SAMLMessageStorageFactory sAMLMessageStorageFactory() 
        return new EmptyStorageFactory();
    

    
@Autowired(required=false)
    @Qualifier("samlFilter")
    FilterChainProxy samlFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception 
       ...
       // Only try to do SAML stuff after we have tried to authenticate the user.
       http.addFilterAfter(samlFilter, RememberMeAuthenticationFilter.class)
       
       // (Optional part if you want redirects)
       // Just before we get to the samlFilter if we have not yet authenticated we
       // may set a cookie storing the location to which we should redirect back to
       // when all is said and done.
       http.addFilterBefore(setRedirectCookieForPostSAMLAction, samlFilter.getClass());
       // On SAML auth success, apply the redirect from the cookie. 
       sAMLProcessingFilter.setAuthenticationSuccessHandler(new ReadRedirectCookieForSAMLSuccessHandler());
       // (End Optional part)
       ...
       // Don't forget to enable your token based remember me service
       // Also don't forget to set stateless
       http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    

最后,如果您确实想支持某种形式的重定向,请执行以下操作:

让您的 UI 将您重定向到某个特殊的 URL,并在 GET 参数中记录要访问的 URL。例如。如果您出现在/secure.html,用户界面会将您重定向到/saml-redirect.html?redirectTo=/secure.html。 创建一个过滤器SetRedirectCookieForPostSAMLAction,如果用户要去saml-redirec.html 并且未通过身份验证,则会设置一个记录redirectTo 值的cookie。在 SAML 过滤器将用户重定向到 IDP 之前调用此过滤器。

public class setRedirectCookieForPostSAMLAction implements Filter 
   void setRedirectCookieIfRequired(HttpServletRequest request, HttpServletResponse response, Authentication authentication) 
        // If the user is not authenticated and is going to the saml redirect page
        if(authentication == null && 
            new AntPathRequestMatcher("/saml-redirect.html", null).matches(request)) 
            if(request has a redirectTo param) 
                 Set cookie "saml-redirect-post-action" to Base64(redirectTo);
            
        



创建一个成功处理程序ReadRedirectCookieForSAMLSuccessHandler,它将在用户使用 SSO 成功登录时运行(如上配置)。如果重定向 cookie,此成功处理程序只需要重定向用户。它还应该清除 cookie 重定向 cookie。

(不要忘记检查重定向看起来是否合法,并且只在重定向用户之前转到您的应用程序。)

【讨论】:

以上是关于使用 Spring Security Saml 和 SP 应用程序的无状态会话的主要内容,如果未能解决你的问题,请参考以下文章

Spring 框架 4.0 和 Spring security 3.2.4 上的 Spring Security SAML 扩展

使用 spring-security-saml 在应用程序中没有配置 IDP 错误

Java 配置中的 Spring Security XML 配置和 Spring SAML

Spring Security SAML 示例

使用 Spring Security Saml 和 SP 应用程序的无状态会话

Spring Security 和嵌套 FilterChainProxy 编写 SAML Service Provider