Spring Плагин безопасности SAML - ни один хостинг-провайдер не настроил исключение
Я пытаюсь интегрировать SSO SAML с Spring безопасностью с помощью расширения wma5 w260 безопасности SAML. Раньше мне удалось запустить доказательство концепции, которое было найдено здесь: https://github.com/vdenotaris/spring-boot-security-saml-sample. К сожалению, после переноса конфигурации в мой проект она работает некорректно.
После анализа журналов я выяснил, что мое приложение (SP) правильно загружает метаданные IdP из предоставленного URL. Однако, пытаясь загрузить метаданные моего SP, попробовав https://localhost:8443/saml/metadata в браузере, выдается следующее исключение:
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 не может определить идентификатор объекта моего приложения. Я настраиваю его так:
// 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", который должен быть до "metadataDisplayFilter", вообще не был добавлен в цепочку фильтров. Когда я сменил 'samlFilter' на 'springSecurityFilter', все начало работать. Это было нелегко найти из-за моего нестандартного использования Jetty.
Благодарим за помощь!
Ответ 2
У вас настроен IDP?
Ответ 3
В MetadataGenerator entityId - это общий ключ, который вы используете для связи с вашим IDP, к которому ваше приложение хочет получить к нему доступ. На стороне IDP есть samlConfiguration, где вам нужно ввести тот же объект entityId, чтобы ваше приложение могло получить доступ к пользователям IDP.
<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>