为啥 Spring SAML 会阻止 Spring OAuth2 工作?

Posted

技术标签:

【中文标题】为啥 Spring SAML 会阻止 Spring OAuth2 工作?【英文标题】:Why is Spring SAML preventing Spring OAuth2 from working?为什么 Spring SAML 会阻止 Spring OAuth2 工作? 【发布时间】:2018-10-12 04:11:39 【问题描述】:

我正在将 Spring SAML 添加到一些迄今为止仅使用 OAuth2 的软件中。我需要确保 OAuth 仍然有效,因为 SAML 仅适用于我们的部分客户。

我遇到了一个问题,旧的 oAuth 似乎不再起作用(尽管 SAML 大部分都可以)。似乎身份验证管理器正在以某种方式被覆盖,但尚不清楚如何或为什么。这是我的 WebSecurityConfig.java 中的相关代码:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception 
    auth.userDetailsService(userDetailsService)
            .passwordEncoder(passwordService.getEncoder())
            .and()
            .authenticationProvider(samlAuthenticationProvider)
            .authenticationProvider(oAuth2AuthenticationProvider());

还有 SAMLConfig.java:

@Bean
public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception 
    SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
    samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager());
    samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
    samlWebSSOProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
    return samlWebSSOProcessingFilter;


@Bean
public AuthenticationManager authenticationManager() 
    return new ProviderManager(Collections.singletonList(samlAuthenticationProvider()));

显然,这是错误的,但不清楚如何纠正它。

当我调试时,AuthenticationManagerBuilder.performBuild() 在启动时被调用了 3 次。

第一次使用 SAML、OAuth2 和 Dao AuthenticationProviders 构建一个。 第二次使用 AnonymousAuthenticationProvider 构建一个。 第三次与另一个 DaoAuthenticationProvider 构建一个。

登录时,ProviderManager.authenticate() 会被调用两次。

第一次,它只有一个提供者,即 AnonymousAuthenticationProvider。这不会进行身份验证。 第二次是第一次上级经理。它只有一个提供者,即 SAMLAuthenticationProvider。如果在 SAML 中找不到与我进行身份验证的用户,这仍然是最后一个被调用的提供者或管理器。

为什么?如何更正此问题,以便在某些情况下将凭据定向到 SAML,在所有其他情况下将凭据定向到 OAuth,或者允许在 SAML 中不起作用的任何凭据溢出到 OAuth?

【问题讨论】:

您正在通过authenticationManager 方法注册一个全局AuthenticationManager。你不应该那样做。 @M.Deinum 好的。你能详细说明一下吗?我正在关注几个这样做的例子。 见github.com/vdenotaris/spring-boot-security-saml-sample/blob/…。你的SAMLConfig 也应该扩展WebSecurityCOnfiger 或者甚至更好的你想把它放在一个WebSecurityConfig 这样你就可以获得共享的authenticationManager @M.Deinum 好的。是什么让这种方法正确?我的部分问题涉及“为什么”,因为我喜欢理解而不是盲目遵循。也许这可能是一个答案? 为什么是我的第一条评论。您正在提供自己的全局身份验证管理器,它只包含 SAML 身份验证提供程序,这基本上会使您的 configureAuthenticationManagerBuilder 无用。 【参考方案1】:

new ProviderManager() 创建一个 AuthenticationManager 跳过构建器进程,这就是调试 performBuild() 时它不显示的原因。

authenticationManager() bean 方法旨在返回现有的全局 AuthenticationManager,但问题使用它的方式改为返回一个新的不同的 AuthenticationManager,覆盖构建器返回的内容。这就是为什么它确实在调试authenticate() 时出现,而构建的 AuthenticationManager 却没有。

解决方案是将现有的 AuthenticationManager 传递给SAMLProcessingFilter.setAuthenticationManager(),而不是一个新的。我这样做的方法是将所有代码从 SAMLConfig.java 移动到 WebSecurityConfig.java,这更简单,但这不是唯一的方法。

【讨论】:

遇到了一个非常相似的问题。可以分享一下配置吗?

以上是关于为啥 Spring SAML 会阻止 Spring OAuth2 工作?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 Spring Saml 中忽略 cacerts?

为啥 Spring SAML SP 需要 keystore 和相关的 key 配置?

为啥在 Spring 响应式 Mongo 中订阅有效而阻止无效?

spring security saml使用哪个密钥?

元数据刷新死锁(spring-security-saml)

获取 https://localhost/myapp/saml/sso 重定向会引发 404 错误 - Spring MVC/Okta