Spring security 使用Spring Security Saml和SP应用程序的无状态会话
我试着从, 我能够运行它并与身份提供商集成 但是,我看到每次都会创建一个会话,并一直保持到用户注销为止 我在spring boot中使用基于资源的服务,因此不希望增加会话的开销 我尝试将下面的行添加到configure方法中, http.sessionManagement() .sessionCreationPolicy(sessionCreationPolicy.STATELESS) 但是,在这个设置下,我总是被要求登录到身份提供者 如果我登录,它会返回页面,要求我在循环中再次登录 我不确定这是否是禁用会话时的正确行为 任何人都能为我提供使用SpringSecuritySAML扩展和服务提供商应用程序的无状态会话的正确方法吗 谢谢Spring security 使用Spring Security Saml和SP应用程序的无状态会话,spring-security,spring-boot,httpsession,spring-saml,Spring Security,Spring Boot,Httpsession,Spring Saml,我试着从, 我能够运行它并与身份提供商集成 但是,我看到每次都会创建一个会话,并一直保持到用户注销为止 我在spring boot中使用基于资源的服务,因此不希望增加会话的开销 我尝试将下面的行添加到configure方法中, http.sessionManagement() .sessionCreationPolicy(sessionCreationPolicy.STATELESS) 但是,在这个设置下,我总是被要求登录到身份提供者 如果我登录,它会返回页面,要求我在循环中再次登录 我不确定
Sri对于SAML身份验证部分,您确实需要一个会话,因此您有两个选项: 1) 在应用程序中有两种不同的安全上下文,一种用于SAML身份验证,另一种用于无状态服务。不确定如何对服务进行身份验证,但它必须具有某种令牌身份验证才能成为无状态的。 您可以定义2
websecurityConfigureAdapter
并覆盖configure(HttpSecurity http)
方法。然后在saml配置中使用http.requestMatchers(“/saml/**”)
,在服务配置中使用http.requestMatchers(“/service/**”)
,然后/saml
下的所有内容都将通过saml auth,而/service
下的所有内容都将通过您拥有的其他内容
2) 在SAML配置中添加更多过滤器(在SAML过滤器之前),使其与不同类型的身份验证(例如基于令牌的身份验证)一起工作,并且只要此过滤器能够在SAML过滤器之前生成有效的身份验证
,您就应该是好的
您还可以签出此库:要简化SAML配置,在无状态下启用SAML,您需要:
- 将SamlMessageStoreFactory设置为空工厂
- 确保SAML筛选器位于“记住我”筛选器之后
- 实际上,启用无状态并像往常一样配置您的“记住我”服务
- 让UI将您重定向到某个特殊URL,并在GET参数中记录要转到的URL。例如,如果您出现在
,UI会将您重定向到/secure.html
/saml redirect.html?redirectTo=/secure.html
- 创建一个过滤器
,如果用户要SetRedirectCookieForPostSAMLAction
且未经过身份验证,则该过滤器将设置一个cookie,记录saml redirec.html
值。在SAML筛选器将用户重定向到IDP之前调用此筛选器重定向到
- 创建一个成功处理程序
,当用户使用SSO(上面配置)成功登录时将运行该处理程序。如果重定向cookie失败,则此成功处理程序只需重定向用户。它还应该清除cookie重定向cookieReadRedirectCookieForSAMLSuccessHandler
(别忘了检查重定向是否合法,并且在重定向用户之前只转到你的应用。)嗨,Sri,我们的项目中也有同样的要求。你能告诉我你是如何实施的吗。提前谢谢。KittyHi Sam,我尝试了与您建议的相同的方法,在saml身份验证之后,当用户使用不同的端点进行下一次调用时,spring允许它命中端点。但是第二个端点是无状态的,我创建了一个过滤器,并使用不同的逻辑使其验证成功。过滤器中使用的逻辑现在没有用处,因为spring认为它已经通过了身份验证。为了在rest端点实现(/saml/**)中解决这个问题,我将使会话无效。但我觉得这不是正确的方法。请告诉我是否有更好的解决办法-KittyI认为1)中不清楚的是如何阻止spring使用它在SAML身份验证期间创建的jsessionid,使其不能在
“/service/**”
下使用,spring似乎看到了jsessionid,并假设请求在所有地方都经过了身份验证。在一天结束时,spring安全性只是向执行的每个请求添加了一系列筛选器,其中一个是会话筛选器。您可以修改该链并插入自己的条件会话筛选器,或者拥有不同的“领域”,这些“领域”对于不同的路径基本上是不同的筛选器链,您可以使用WebSecurityConfigureAdapter定义它们
@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);
}
}
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);
}
}
}
}