spring-saml多租户环境中的端点验证方法

问题描述

我正在构建多租户环境。 您需要能够访问https://tenant1.comhttps://tenant2.com上的一个应用。

事实证明,要为每个URL指定SP元数据,可以通过给元数据一个别名来指定它。 但是,端点验证也需要相应。

在samlContextProviderLB的ServerName中设置了

tenant1.com在这种状态下 使用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,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();
        }
    }


}

作为解决问题的方法

在samlContextProviderLB中设置多个serverNames

请勿执行端点验证

可以考虑。 但是,我不知道具体的实现方法。 救救我!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...