Spring security spring saml多租户环境下的端点验证方法

Spring security spring saml多租户环境下的端点验证方法,spring-security,saml,multi-tenant,spring-saml,Spring Security,Saml,Multi Tenant,Spring Saml,我正在构建一个多租户环境。 您需要能够在https://tenant1.com或https://tenant2.com 事实证明,要为每个URL指定SP元数据,可以通过为元数据指定别名来指定。 然而,端点验证也需要相应地进行 tenant1.com是在samlContextProviderLB的服务器名中设置的。在这种状态下 使用https://tenant2.com,出现以下错误 SAML消息目标端点'https://tenant2.com/xxx' 与收件人终结点的名称不匹配https://

我正在构建一个多租户环境。 您需要能够在
https://tenant1.com
https://tenant2.com

事实证明,要为每个URL指定SP元数据,可以通过为元数据指定别名来指定。 然而,端点验证也需要相应地进行

tenant1.com
是在samlContextProviderLB的服务器名中设置的。在这种状态下 使用
https://tenant2.com
,出现以下错误

SAML消息目标端点'https://tenant2.com/xxx' 与收件人终结点的名称不匹配https://tenant1.com/xxx"

以下是一些securityConfig设置

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SecurityProperties securityProperties;

    ・
    ・
    ・
    
    @Bean
    public SAMLContextProviderLB contextProvider() {
        SAMLContextProviderLB samlContextProviderLB = new SAMLContextProviderLB();
        samlContextProviderLB.setScheme("https");
        samlContextProviderLB.setServerName("tenant1.com");
        samlContextProviderLB.setServerPort(443);
        samlContextProviderLB.setIncludeServerPortInRequestURL(false);
        samlContextProviderLB.setContextPath("");
        EmptyStorageFactory emptyStorageFactory = new EmptyStorageFactory();
        samlContextProviderLB.setStorageFactory(emptyStorageFactory);
        return samlContextProviderLB;

    }

    @Bean
    public ExtendedMetadataDelegate ssoCircleExtendedMetadataProvider1()
            throws MetadataProviderException, ResourceException {
        ClasspathResource classpathResource = new ClasspathResource("/metadata/sp_metadata2.xml");
        ResourceBackedMetadataProvider resourceBackedMetadataProvider = new ResourceBackedMetadataProvider(
                this.backgroundTaskTimer, classpathResource);
        resourceBackedMetadataProvider.setParserPool(parserPool());
        ExtendedMetadata extendedMetadata = new ExtendedMetadata();
        extendedMetadata.setAlias("alias-tenant1");
        extendedMetadata.setLocal(true);
        extendedMetadata.setSigningKey("keyVal");
        extendedMetadata.setEncryptionKey("keyVal");
        extendedMetadata.setIdpDiscoveryEnabled(false);
        extendedMetadata.setIdpDiscoveryURL("https://login.windows.net/xxx..../saml2");
        ExtendedMetadataDelegate extendedMetadataDelegate = new ExtendedMetadataDelegate(resourceBackedMetadataProvider,
                extendedMetadata);
        backgroundTaskTimer.purge();
        return extendedMetadataDelegate;
    }

    @Bean
    public ExtendedMetadataDelegate idpExtendedMetadataProvider1()
            throws MetadataProviderException, ResourceException {
        ClasspathResource classpathResource = new ClasspathResource("/metadata/idp_metadata1.xml");
        ResourceBackedMetadataProvider resourceBackedMetadataProvider = new ResourceBackedMetadataProvider(
                this.backgroundTaskTimer, classpathResource);
        resourceBackedMetadataProvider.setParserPool(parserPool());
        ExtendedMetadataDelegate extendedMetadataDelegate = new ExtendedMetadataDelegate(
                resourceBackedMetadataProvider);
        backgroundTaskTimer.purge();
        return extendedMetadataDelegate;
    }

    public ExtendedMetadataDelegate ssoCircleExtendedMetadataProvider2()
            throws MetadataProviderException, ResourceException {
        ClasspathResource classpathResource = new ClasspathResource("/metadata/sp_metadata2.xml");
        ResourceBackedMetadataProvider resourceBackedMetadataProvider = new ResourceBackedMetadataProvider(
                this.backgroundTaskTimer, classpathResource);
        resourceBackedMetadataProvider.setParserPool(parserPool());
        ExtendedMetadata extendedMetadata = new ExtendedMetadata();
        extendedMetadata.setAlias("alias-tenant2");
        extendedMetadata.setLocal(true);
        extendedMetadata.setSigningKey("keyVal");
        extendedMetadata.setEncryptionKey("keyVal");
        extendedMetadata.setIdpDiscoveryEnabled(false);
        extendedMetadata.setIdpDiscoveryURL("https://login.windows.net/xxx..../saml2");
        ExtendedMetadataDelegate extendedMetadataDelegate = new ExtendedMetadataDelegate(resourceBackedMetadataProvider,
                extendedMetadata);
        backgroundTaskTimer.purge();
        return extendedMetadataDelegate;
    }

    public ExtendedMetadataDelegate idpExtendedMetadataProvider2()
            throws MetadataProviderException, ResourceException {
        ClasspathResource classpathResource = new ClasspathResource("/metadata/idp_metadata2.xml");
        ResourceBackedMetadataProvider resourceBackedMetadataProvider = new ResourceBackedMetadataProvider(
                this.backgroundTaskTimer, classpathResource);
        resourceBackedMetadataProvider.setParserPool(parserPool());
        ExtendedMetadataDelegate extendedMetadataDelegate = new ExtendedMetadataDelegate(
                resourceBackedMetadataProvider);
        backgroundTaskTimer.purge();
        return extendedMetadataDelegate;
    }

    @Bean
    @Qualifier("metadata")
    public CachingMetadataManager metadata() throws MetadataProviderException, ResourceException {
        List<MetadataProvider> providers = new ArrayList<MetadataProvider>();
        // SP MetaData
        providers.add(ssoCircleExtendedMetadataProvider1());
        providers.add(ssoCircleExtendedMetadataProvider2());
        // IDP MetaData
        providers.add(idpExtendedMetadataProvider1());
        providers.add(idpExtendedMetadataProvider2());

        CachingMetadataManager cachingMetadataManager = new CachingMetadataManager(providers);
        cachingMetadataManager.setDefaultIDP("https://sts.windows.net/xxx..../");
        return cachingMetadataManager;
    }


    ・
    ・
    ・

    @Bean
    public FilterChainProxy samlFilter() throws Exception {
        List<SecurityFilterChain> chains = new ArrayList<SecurityFilterChain>();
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/login/**"),
                samlEntryPoint()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/samlForceLogin/**"),
                samlForceEntryPoint()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/logout/**"),
                samlLogoutFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/metadata/**"),
                metadataDisplayFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSO/**"),
                samlWebSSOProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSOHoK/**"),
                samlWebSSOHoKProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SingleLogout/**"),
                samlLogoutProcessingFilter()));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/discovery/**"),
                samlIDPDiscovery()));
        return new FilterChainProxy(chains);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.httpBasic()
            .authenticationEntryPoint(samlEntryPoint())
            .authenticationEntryPoint(samlForceEntryPoint());
        
        http.csrf()
            .ignoringAntMatchers("/saml/**")
            .ignoringAntMatchers("/");
            
        http.addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);
        
        http.authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/saml/**").permitAll()
            .anyRequest().authenticated();
            
        http.logout()
            .logoutSuccessUrl("/");

        http.headers().xssProtection();

        if (securityProperties.isEnableCsrf()) {
            http.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class).csrf();
        } else {
            http.csrf().disable();
        }
    }


}

@配置
@启用Web安全性
@EnableGlobalMethodSecurity(securedEnabled=true)
公共类SecurityConfig扩展了WebSecurity配置适配器{
@自动连线
私人证券财产证券财产;
・
・
・
@豆子
公共SAMLContextProviderLB contextProvider(){
SAMLContextProviderLB SAMLContextProviderLB=新的SAMLContextProviderLB();
samlContextProviderLB.setScheme(“https”);
samlContextProviderLB.setServerName(“tenant1.com”);
samlContextProviderLB.setServerPort(443);
samlContextProviderLB.setIncludeServePortInRequestUrl(false);
samlContextProviderLB.setContextPath(“”);
EmptyStorageFactory EmptyStorageFactory=新的EmptyStorageFactory();
samlContextProviderLB.设置存储工厂(清空存储工厂);
返回samlContextProviderLB;
}
@豆子
public ExtendedMetadataDelegate SSOCirleExtendedMetadataProvider1()
抛出MetadataProviderException、ResourceException{
ClasspathResource ClasspathResource=new ClasspathResource(“/metadata/sp_metadata2.xml”);
ResourceBackedMetadataProvider ResourceBackedMetadataProvider=新ResourceBackedMetadataProvider(
this.backgroundTaskTimer,classpathResource);
setParserPool(parserPool());
ExtendedMetadata ExtendedMetadata=新的ExtendedMetadata();
setAlias(“alias-tenant1”);
extendedMetadata.setLocal(true);
extendedMetadata.setSigningKey(“keyVal”);
setEncryptionKey(“keyVal”);
extendedMetadata.SetIdDiscoveryEnabled(false);
extendedMetadata.SetIdDiscoveryUrl(“https://login.windows.net/xxx..../saml2");
ExtendedMetadataDelegate ExtendedMetadataDelegate=新的ExtendedMetadataDelegate(resourceBackedMetadataProvider,
扩展元数据);
backgroundTaskTimer.purge();
返回extendedMetadataDelegate;
}
@豆子
公共ExtendedMetadataDelegate IdExtendedMetadataProvider1()
抛出MetadataProviderException、ResourceException{
ClasspathResource ClasspathResource=new ClasspathResource(“/metadata/idp_metadata1.xml”);
ResourceBackedMetadataProvider ResourceBackedMetadataProvider=新ResourceBackedMetadataProvider(
this.backgroundTaskTimer,classpathResource);
setParserPool(parserPool());
ExtendedMetadataDelegate ExtendedMetadataDelegate=新的ExtendedMetadataDelegate(
resourceBackedMetadataProvider);
backgroundTaskTimer.purge();
返回extendedMetadataDelegate;
}
public ExtendedMetadataDelegate SSOCirleExtendedMetadataProvider2()
抛出MetadataProviderException、ResourceException{
ClasspathResource ClasspathResource=new ClasspathResource(“/metadata/sp_metadata2.xml”);
ResourceBackedMetadataProvider ResourceBackedMetadataProvider=新ResourceBackedMetadataProvider(
this.backgroundTaskTimer,classpathResource);
setParserPool(parserPool());
ExtendedMetadata ExtendedMetadata=新的ExtendedMetadata();
setAlias(“别名-tenant2”);
extendedMetadata.setLocal(true);
extendedMetadata.setSigningKey(“keyVal”);
setEncryptionKey(“keyVal”);
extendedMetadata.SetIdDiscoveryEnabled(false);
extendedMetadata.SetIdDiscoveryUrl(“https://login.windows.net/xxx..../saml2");
ExtendedMetadataDelegate ExtendedMetadataDelegate=新的ExtendedMetadataDelegate(resourceBackedMetadataProvider,
扩展元数据);
backgroundTaskTimer.purge();
返回extendedMetadataDelegate;
}
公共ExtendedMetadataDelegate IdExtendedMetadataProvider2()
抛出MetadataProviderException、ResourceException{
ClasspathResource ClasspathResource=new ClasspathResource(“/metadata/idp_metadata2.xml”);
ResourceBackedMetadataProvider ResourceBackedMetadataProvider=新ResourceBackedMetadataProvider(
this.backgroundTaskTimer,classpathResource);
setParserPool(parserPool());
ExtendedMetadataDelegate ExtendedMetadataDelegate=新的ExtendedMetadataDelegate(
resourceBackedMetadataProvider);
backgroundTaskTimer.purge();
返回extendedMetadataDelegate;
}
@豆子
@限定符(“元数据”)
public CachingMetadataManager元数据()引发MetadataProviderException,ResourceException{
列表提供程序=新的ArrayList();
//SP元数据
add(ssoCircleExtendedMetadataProvider1());
add(ssoCircleExtendedMetadataProvider2());
//IDP元数据
add(idpExtendedMetadataProvider1());
add(idpExtendedMetadataProvider2());
cachingmetadatmanager cachingmetadatmanager=新cachingmetadatmanager(提供程序);
cachingMetadataManager.setDefaultIDP(“https://sts.windows.net/xxx..../");
返回cachingmetadata管理器;