java - tutorial - Complemento de SAML de Spring Security: no se configuró ningún proveedor de servicios alojados
spring security tutorial español pdf (3)
Estoy tratando de integrar SAML SSO con Spring Security usando Spring Security SAML extension. Antes, logré ejecutar una prueba de concepto que se encuentra aquí: https://github.com/vdenotaris/spring-boot-security-saml-sample . Lamentablemente, después de mover la configuración a mi proyecto, no está funcionando correctamente.
Después de analizar los registros, descubrí que mi aplicación (SP) está descargando correctamente los metadatos IdP de la URL proporcionada. Sin embargo, después de intentar descargar los metadatos de mi SP intentando https: // localhost: 8443 / saml / metadata en el navegador, se lanza la siguiente excepción:
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
Después de la depuración, no pude averiguar por qué Spring no puede descifrar el ID de entidad de mi aplicación. Lo estoy configurando así:
// 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;
}
Por supuesto, la propiedad saml.entity-id se descarga correctamente desde mi configuración. Toda la configuración de seguridad está aquí: https://gist.github.com/mc-suchecki/671ecb4d5ae4bae17f81
El orden de los filtros es correcto: el filtro del generador de metadatos está antes del filtro SAML. No estoy seguro de que sea relevante, supongo que no, pero mi aplicación no utiliza Spring Boot, y la aplicación de muestra (el origen de la configuración) sí lo está.
Gracias de antemano por cualquier ayuda.
¿Tiene un IDP configurado?
En MetadataGenerator entityId es una clave compartida que utiliza para comunicarle a su IDP que su aplicación desea acceder a ella. En el lado de IDP hay una configuración de saml donde necesita ingresar el mismo entityID para permitir que su aplicación acceda a los usuarios de 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>
Encontré el problema esta semana. Hubo un problema con los filtros. Uno de los métodos fue crear el ''samlFilter'', así:
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);
}
Después de eso, otro método fue establecer toda la cadena de filtros para Spring, así:
@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("/");
}
Eso fue perfectamente correcto. Sin embargo, cuando estaba lanzando la aplicación usando el servidor Jetty, estaba tratando de conectar solo el ''samlFilter'' al contexto de la aplicación. Por eso, el ''metadataGeneratorFilter'' que debe estar antes del ''metadataDisplayFilter'' no se agregó a la cadena de filtros. Cuando cambié ''samlFilter'' a ''springSecurityFilter'', todo comenzó a funcionar. Eso no fue fácil de encontrar, debido a mi uso no estándar de Jetty.
¡Gracias por tu ayuda!