web-dev-qa-db-ja.com

Spring SecuritySAMLプラグイン-ホストされたサービスプロバイダーが構成されていない例外

Spring SecuritySAML拡張機能を使用してSAMLSSOをSpringSecurityと統合しようとしています。以前、私はここにある概念実証を実行することに成功しました: https://github.com/vdenotaris/spring-boot-security-saml-sample 。残念ながら、構成をプロジェクトに移動した後、正しく機能していません。

ログを分析した後、アプリケーション(SP)が提供されたURLからIdPメタデータを正しくダウンロードしていることがわかりました。ただし、ブラウザで https:// localhost:8443/saml/metadata を試行してmy SPのメタデータをダウンロードしようとすると、次の例外がスローされます。

javax.servlet.ServletException: Error initializing metadata
at org.springframework.security.saml.metadata.MetadataDisplayFilter.processMetadataDisplay(MetadataDisplayFilter.Java:120)
at org.springframework.security.saml.metadata.MetadataDisplayFilter.doFilter(MetadataDisplayFilter.Java:88)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.Java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.Java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:262)
at org.Eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.Java:1645)
at org.Eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.Java:564)
at org.Eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.Java:143)
at org.Eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.Java:578)
at org.Eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.Java:221)
at org.Eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.Java:1111)
at org.Eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.Java:498)
at org.Eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.Java:183)
at org.Eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.Java:1045)
at org.Eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.Java:141)
at org.Eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.Java:98)
at org.Eclipse.jetty.server.Server.handle(Server.Java:461)
at org.Eclipse.jetty.server.HttpChannel.handle(HttpChannel.Java:284)
at org.Eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.Java:244)
at org.Eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.Java:534)
at org.Eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.Java:607)
at org.Eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.Java:536)
at Java.lang.Thread.run(Thread.Java:745)
Caused by: org.opensaml.saml2.metadata.provider.MetadataProviderException: No hosted service provider is configured and no alias was selected
    at org.springframework.security.saml.context.SAMLContextProviderImpl.populateLocalEntity(SAMLContextProviderImpl.Java:311)
    at org.springframework.security.saml.context.SAMLContextProviderImpl.populateLocalContext(SAMLContextProviderImpl.Java:216)
    at org.springframework.security.saml.context.SAMLContextProviderImpl.getLocalEntity(SAMLContextProviderImpl.Java:107)
    at org.springframework.security.saml.metadata.MetadataDisplayFilter.processMetadataDisplay(MetadataDisplayFilter.Java:114)
    ... 24 more

デバッグ後、SpringがアプリケーションのエンティティIDを把握できない理由を理解できませんでした。私はそれを次のように設定しています:

// Filter automatically generates default SP metadata
@Bean
public MetadataGenerator metadataGenerator() {
    MetadataGenerator metadataGenerator = new MetadataGenerator();
    metadataGenerator.setEntityId(environment.getRequiredProperty("saml.entity-id"));
    metadataGenerator.setEntityBaseURL("URL is here");
    metadataGenerator.setExtendedMetadata(extendedMetadata());
    metadataGenerator.setIncludeDiscoveryExtension(false);
    metadataGenerator.setKeyManager(keyManager());
    return metadataGenerator;
}

もちろん、saml.entity-idプロパティは私の設定から正しくダウンロードされます。全体のセキュリティ構成はここにあります: https://Gist.github.com/mc-suchecki/671ecb4d5ae4bae17f81

フィルタの順序は正しいです-メタデータジェネレータフィルタはSAMLフィルタの前にあります。それが関連しているかどうかはわかりませんが(おそらくそうではないと思います)、私のアプリケーションはSpring Bootを使用していません。サンプルアプリケーション(構成のソース)は使用しています。

よろしくお願いします。

17
mc.suchecki

今週問題を見つけました。フィルタに問題がありました。メソッドの1つは、次のように「samlFilter」を作成することでした。

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("/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);
}

その後、別の方法は、次のように、Springのフィルターチェーン全体を設定することでした。

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

それは完全に正しかった。ただし、Jettyサーバーを使用してアプリケーションを起動したとき、「samlFilter」のみをアプリケーションコンテキストに接続しようとしていました。そのため、必須である 'metadataGeneratorFilter'はbefore 'metadataDisplayFilter'はフィルターチェーンにまったく追加されませんでした。 'samlFilter'を 'springSecurityFilter'に変更すると、すべてが機能し始めました。 Jettyの非標準的な使用のため、それを見つけるのは簡単ではありませんでした。

ご協力ありがとうございました!

8
mc.suchecki

MetadataGeneratorでは、entityIdは、アプリケーションがIDPにアクセスしたいIDPと通信するために使用する共有キーです。 IDP側には、アプリケーションがIDPユーザーにアクセスできるようにするために同じentityIdを入力する必要があるsamlConfigurationがあります。

<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
    <bean class="org.springframework.security.saml.metadata.MetadataGenerator">              
        <property name="entityId" value="****"/>
        <property name="extendedMetadata">
            <bean class="org.springframework.security.saml.web.MyExtendedMetadata">
                <property name="signMetadata" value="true"/>                        
                <property name="signingKey" value="****"/>
                <property name="encryptionKey" value="****"/>
            </bean>
        </property>
    </bean>
</constructor-arg>
1
Antonio

IDPを構成していますか?

1
Ruddy

これを解決するには、Spring Bootの通常の(セキュリティ以外の)フィルターの自動登録からSAMLフィルターを除外し、フィルターごとにFilterRegistrationBeanを追加します。

  @Bean
  public FilterRegistrationBean disableSAMLEntryPoint() {
    final FilterRegistrationBean registration = 
        new FilterRegistrationBean<>(samlEntryPoint());
    registration.setEnabled(false);
    return registration;
  }
0
itzg