java - Spring Security SAML 插件 - 未配置托管服务提供商异常

标签 java spring spring-security spring-saml

我正在尝试使用 Spring Security SAML 扩展将 SAML SSO 与 Spring Security 集成。之前,我成功地运行了一个在这里找到的概念证明:https://github.com/vdenotaris/spring-boot-security-saml-sample .不幸的是,将配置移至我的项目后,它无法正常工作。

分析日志后,我发现我的应用程序 (SP) 正在从提供的 URL 正确下载 IdP 元数据。但是,在尝试下载我的 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 无法找出我的应用程序的实体 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——而示例应用程序(配置源)是。

提前感谢您的帮助。

最佳答案

我这周发现了这个问题。过滤器有问题。其中一种方法是创建“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”连接到应用程序上下文。因此,要求在“metadataDisplayFilter”之前的“metadataGeneratorFilter”根本没有添加到过滤器链中。当我将“samlFilter”更改为“springSecurityFilter”时,一切都开始工作了。由于我对 Jetty 的非标准使用,这并不容易找到。

感谢您的帮助!

关于java - Spring Security SAML 插件 - 未配置托管服务提供商异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34796633/

相关文章:

java - 在树莓派中编译安卓应用

java - SLF4J记录器的Spring构造函数注入(inject)-如何获取注入(inject)目标类?

spring - 如何使用 spring 集成在电子邮件正文中附加文件

java - Spring-Security 3/Spring MVC 和可怕的@Secured/RequestMapping

Spring 安全 : custom userdetails

java - 尝试 Spring Security 与 Jersey 我的 security-context.xml 文件有什么问题?

java - 将字符串数组从 Java 传递到 C++

java - 将 byte[] 数组转换为 unsigned Long java

java - 查看 Springs 下拉列表的排序顺序

javascript - 我如何链接到 AngularJS 中的 pdf?