在使用 Oauth、SAML 和 spring-security 的多租户的情况下从 spring-security.xml 中获取错误

Posted

技术标签:

【中文标题】在使用 Oauth、SAML 和 spring-security 的多租户的情况下从 spring-security.xml 中获取错误【英文标题】:Getting error from spring-security.xml in case of multi-tenacy with Oauth,SAML, and spring-security 【发布时间】:2015-05-29 08:19:37 【问题描述】:

我需要为我的网络应用程序提供多租户支持。我已经成功添加了对带有 spring-security 的 OAUTH2 的支持。我的应用程序运行正常,并且可以使用正常登录(用户名和密码)以及 OAuth 令牌访问。

但现在我必须为我们的一位客户提供 SSO 支持,因此我为 SP 添加了 Spring-SAML,为 IDP 添加了 ADFS。从现在开始出现问题,我可以使用基于 saml 的 url 或基于 rest 的 URL,但不能同时提供两者。

以下几行来自我的 spring-security.xml 文件

<security:http pattern="/oauth/token" create-session="stateless"
        authentication-manager-ref="clientAuthenticationManager">
        <security:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
        <security:anonymous enabled="false" />
        <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
        <security:custom-filter ref="clientCredentialsTokenEndpointFilter"
            after="BASIC_AUTH_FILTER" />
        <security:access-denied-handler ref="oauthAccessDeniedHandler" />
    </security:http>

    <!-- SAML starts -->

   <security:http entry-point-ref="samlEntryPoint" >
        <security:intercept-url pattern="/oauth/**" access="ROLE_USER" />
        <security:intercept-url pattern="/saml" access="IS_AUTHENTICATED_FULLY"/> 
        <security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
        <security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
    </security:http>

     <!-- SAML ends -->

    <security:http pattern="/rest/**"  access-decision-manager-ref="accessDecisionManager">
        <security:anonymous enabled="false" />
        <security:form-login login-page="/login.html" authentication-success-handler-ref="mercatusSavedRequestHandler"
            authentication-failure-url="/login.jsp?login_error=true"/> 

        <security:intercept-url pattern="/rest/**" access="ROLE_USER" />
        <security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
        <security:custom-filter ref="mercatusAjaxTimeoutFilter" after="EXCEPTION_TRANSLATION_FILTER"/>
        <security:access-denied-handler ref="oauthAccessDeniedHandler"/>
    </security:http>

    <security:http access-denied-page="/login.jsp?login_error=true">
        <security:intercept-url pattern="/index.html" access="ROLE_USER" />
        <security:intercept-url pattern="/saml/**" access="ROLE_USER" />
        <security:intercept-url pattern="/oauth/**" access="ROLE_USER" />    
        <security:intercept-url pattern="/customer/*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />  
        <security:form-login login-page="/login.html" authentication-success-handler-ref="mercatusSavedRequestHandler"
            authentication-failure-url="/login.jsp?login_error=true"/> 
        <security:logout delete-cookies="true" invalidate-session="true" logout-success-url="/login.html"/>
        <security:anonymous />
    </security:http>

下面给出了与saml相关的安全标签

<bean id="samlFilter" class="org.springframework.security.web.FilterChainProxy">
    <security:filter-chain-map request-matcher="ant">
        <security:filter-chain pattern="/saml/login/**" filters="samlEntryPoint"/>
        <security:filter-chain pattern="/saml/logout/**" filters="samlLogoutFilter"/>
        <security:filter-chain pattern="/saml/metadata/**" filters="metadataDisplayFilter"/>
        <security:filter-chain pattern="/saml/SSO/**" filters="samlWebSSOProcessingFilter"/>
        <security:filter-chain pattern="/saml/SSOHoK/**" filters="samlWebSSOHoKProcessingFilter"/>
        <security:filter-chain pattern="/saml/SingleLogout/**" filters="samlLogoutProcessingFilter"/>
        <security:filter-chain pattern="/saml/discovery/**" filters="samlIDPDiscovery"/>
    </security:filter-chain-map>
</bean>

<bean id="samlEntryPoint" class="org.springframework.security.saml.SAMLEntryPoint">
    <property name="defaultProfileOptions">
        <bean class="org.springframework.security.saml.websso.WebSSOProfileOptions">
            <property name="includeScoping" value="false"/>
        </bean>
    </property>
</bean>

当我尝试启动 tomcat 时出现以下错误。

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChainProxy': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: A universal match pattern ('/**') is defined  before other patterns in the filter chain, causing them to be ignored. Please check the ordering in your <security:http> namespace or FilterChainProxy bean configuration
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:383)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4887)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5381)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: A universal match pattern ('/**') is defined  before other patterns in the filter chain, causing them to be ignored. Please check the ordering in your <security:http> namespace or FilterChainProxy bean configuration
    at org.springframework.security.config.http.DefaultFilterChainValidator.checkPathOrder(DefaultFilterChainValidator.java:49)
    at org.springframework.security.config.http.DefaultFilterChainValidator.validate(DefaultFilterChainValidator.java:39)
    at org.springframework.security.web.FilterChainProxy.afterPropertiesSet(FilterChainProxy.java:151)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
    ... 21 more

任何帮助将不胜感激。提前致谢。

【问题讨论】:

【参考方案1】:

您的“SAML 启动”过滤器链未定义模式,因此默认为“/**”,然后您使用 pattern="/rest/**" 定义另一个链。您可能需要在 SAML 中使用模式匹配器,或者将其移到最后,因为它是默认设置。

【讨论】:

但我也使用了 entry-point-ref 和 samlFilter 而不是给出 url 模式。 即使将其移到 end 也会给出相同的异常。 那是因为您有 2 个具有相同模式“/**”的过滤器。 感谢您的帮助,它解决了我的问题。通过 IDP 成功验证后重定向到我的应用程序时遇到另一个问题。我已经发布了另一个问题***.com/questions/29300048/…

以上是关于在使用 Oauth、SAML 和 spring-security 的多租户的情况下从 spring-security.xml 中获取错误的主要内容,如果未能解决你的问题,请参考以下文章

OAuth & OpenID & SAML 工作流程梳理对比

在使用 Oauth、SAML 和 spring-security 的多租户的情况下从 spring-security.xml 中获取错误

单个 Spring Boot 应用程序中的 SAML 和 Oauth2

SAML和OAuth2这两种SSO协议的区别

使用 Spring Oauth2 实现 SAML 断言流

为啥 Spring SAML 会阻止 Spring OAuth2 工作?