Spring 安全 SAML 和 UserDetailsS​​ervice

Spring Security SAML and UserDetailsService

我正在使用 Spring Security 5.6 中内置的实现将 SAML 集成到 Spring 启动应用程序中。许多联机帮助都引用了现已弃用的外部库实现 (https://github.com/spring-projects/spring-security-saml),因此我正在关注此文档:

https://docs.spring.io/spring-security/reference/servlet/saml2/login/index.html

我有这个交互工作,我现在正在从 SAML 进行身份验证。这是配置:

spring:
  security:
    saml2:
      relyingparty:
        registration:
          adfs:
            signing:
              credentials:
                - private-key-location: "file:///C:/tmp/keys/private.key"
                  certificate-location: "file:///C:/tmp/keys/public.crt"
            identityprovider:
              entity-id: << SNIPPED >>
              verification.credentials:
                - certificate-location: "classpath:saml-certificate/adfs.crt"
              singlesignon:
                url: << SNIPPED >>
                sign-request: true

代码现在看起来像这样:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final RelyingPartyRegistrationRepository _relyingPartyRegistrationRepository;

    @Autowired
    public WebSecurityConfig(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository {
        _relyingPartyRegistrationRepository = relyingPartyRegistrationRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // add auto-generation of ServiceProvider Metadata at {baseUrl}/saml2/service-provider-metadata/ims-adfs
        RelyingPartyRegistrationResolver relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(_relyingPartyRegistrationRepository);
        Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());

        http
                .authorizeRequests()
                .antMatchers("/seer.ico", "/monitor", "/**/check").permitAll()
                .anyRequest().authenticated()
                .and().sessionManagement()
                .and().csrf().ignoringAntMatchers("/servers/**/searches")
                .and()
                .saml2Login(withDefaults())
                .saml2Logout(withDefaults())
                .addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);
    }

}

问题是我需要重新映射用户详细信息以设置正确的角色,并将登录限制为具有正确 Linux 权限的用户。正在更正断言中返回的权限;我只需要验证它们是否正确或登录失败。

Spring 安全文档中有一节是关于与 UserDetailsS​​ervice 协调的,这似乎正是我所需要的。

https://docs.spring.io/spring-security/reference/servlet/saml2/login/authentication.html#servlet-saml2login-opensamlauthenticationprovider-userdetailsservice

然而,当我像示例一样实现它时,我现在从 Spring 得到以下错误:

No assertions found in response.

这是更新后的代码:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final RelyingPartyRegistrationRepository _relyingPartyRegistrationRepository;

    private final AuthenticationService _userDetailsService;

    @Autowired
    public WebSecurityConfig(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository, AuthenticationService userDetailsService) {
        _relyingPartyRegistrationRepository = relyingPartyRegistrationRepository;
        _userDetailsService = userDetailsService;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
         OpenSaml4AuthenticationProvider authenticationProvider = new OpenSaml4AuthenticationProvider();
         authenticationProvider.setResponseAuthenticationConverter(responseToken -> {
             Saml2Authentication authentication = OpenSaml4AuthenticationProvider.createDefaultResponseAuthenticationConverter().convert(responseToken);

             Assertion assertion = responseToken.getResponse().getAssertions().get(0);
             String username = assertion.getSubject().getNameID().getValue();

             UserDetails userDetails = _userDetailsService.loadUserByUsername(username);
             authentication.setDetails(userDetails);

             return authentication;
         });

        // add auto-generation of ServiceProvider Metadata at {baseUrl}/saml2/service-provider-metadata/ims-adfs
        RelyingPartyRegistrationResolver relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(_relyingPartyRegistrationRepository);
        Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());

        http
                .authorizeRequests()
                .antMatchers("/seer.ico", "/monitor", "/**/check").permitAll()
                .anyRequest().authenticated()
                .and().sessionManagement()
                .and().csrf().ignoringAntMatchers("/servers/**/searches")
                .and()
                .saml2Login(saml2 -> saml2.authenticationManager(new ProviderManager(authenticationProvider)))
                .saml2Logout(withDefaults())
                .addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);
    }
}

所以基本上这从 SAML 得到了正确的响应:

.saml2Login(withDefaults())

当我切换到这个时,SAML 响应缺少断言:

.saml2Login(saml2 -> saml2.authenticationManager(new ProviderManager(authenticationProvider)))

我一直在寻找其他解决方案,但正如我所说,很少有示例不使用旧的已弃用的 SAML 库 Spring。

有什么想法吗?

检查 Spring Boot 是否正在导入版本 3 和版本 4 打开 SAML。如果仅使用版本 4.

Spring 安全示例有一个 SAML2 示例。项目中的build.gradle包含以下内容:

repositories {
    mavenCentral()
    maven { url "https://repo.spring.io/milestone" }
    maven { url "https://repo.spring.io/snapshot" }
    maven { url "https://build.shibboleth.net/nexus/content/repositories/releases/" }
}

dependencies {
    constraints {
        implementation "org.opensaml:opensaml-core:4.1.1"
        implementation "org.opensaml:opensaml-saml-api:4.1.1"
        implementation "org.opensaml:opensaml-saml-impl:4.1.1"
    }
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.security:spring-security-saml2-service-provider'
    implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'

    testImplementation 'net.sourceforge.htmlunit:htmlunit:2.44.0'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    testImplementation 'org.awaitility:awaitility:4.2.0'
}

参考文献: