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を使用していません。サンプルアプリケーション(構成のソース)は使用しています。
よろしくお願いします。
今週問題を見つけました。フィルタに問題がありました。メソッドの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の非標準的な使用のため、それを見つけるのは簡単ではありませんでした。
ご協力ありがとうございました!
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>
IDPを構成していますか?
これを解決するには、Spring Bootの通常の(セキュリティ以外の)フィルターの自動登録からSAMLフィルターを除外し、フィルターごとにFilterRegistrationBean
を追加します。
@Bean
public FilterRegistrationBean disableSAMLEntryPoint() {
final FilterRegistrationBean registration =
new FilterRegistrationBean<>(samlEntryPoint());
registration.setEnabled(false);
return registration;
}