繁体   English   中英

Spring Security的许多提供商

[英]Spring Security many providers

在我的应用程序中,我使用LDAP身份验证(称为ldap )。 对于我的页面之一,我需要使用基本的html弹出窗口(称为internal )进行身份验证。 我得到BeanCreationException

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:1512) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628) ~[spring-beans-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) ~[spring-context-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) ~[spring-context-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389) ~[spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294) ~[spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) [spring-web-3.2.2.RELEASE.jar:3.2.2.RELEASE]
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973) [catalina.jar:7.0.52]
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467) [catalina.jar:7.0.52]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:7.0.52]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) [catalina.jar:7.0.52]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) [catalina.jar:7.0.52]
at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.7.0_51]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.7.0_51]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.7.0_51]
at java.lang.Thread.run(Unknown Source) [na:1.7.0_51]

这是我的配置:

<http authentication-manager-ref="internal">    
    <intercept-url pattern="/monitoring" access="ROLE_USER" />
    <http-basic />
</http>

<http authentication-manager-ref="ldap" auto-config='true' use-expressions="true">
    <intercept-url pattern="/**" access="permitAll" />
    <form-login login-page='/' default-target-url='/login_ok'
        always-use-default-target='true' authentication-failure-url="/login_failed" />
    <logout logout-success-url="/" />
</http>

<authentication-manager id="internal">
   <authentication-provider>
       <user-service>
       <user name="monitoring" password="monitoring" authorities="ROLE_USER" />
       </user-service>
   </authentication-provider>
</authentication-manager>

<authentication-manager erase-credentials="false" id="ldap">
    <ldap-authentication-provider
        group-search-filter="${ldap.group-search-filter}" server-ref="ldapServer"
        group-search-base="${ldap.group-search-base}" user-search-filter="${ldap.user-search-filter}"
        user-search-base="${ldap.user-search-base}" group-role-attribute="${ldap.group-role-attribute}"
        role-prefix="${ldap.role-prefix}">
    </ldap-authentication-provider>
    <authentication-provider user-service-ref="userService" />
</authentication-manager>

我了解为什么会引发异常,并且知道模式顺序和作用域很重要,但不知道如何正确执行。 我想要的是,每个用户都可以访问“ / **”, 但是只有监视用户可以访问/ monitoring(已通过基本身份验证)。 在我想添加此内部身份验证之前,一切工作都很好。

您需要进行的更改是:

  • 确保第一个<http>具有模式。 这是您当前问题的核心。 两个<http>匹配每个请求,因此永远不会考虑第二个<http> 要解决此问题,请添加pattern属性。
  • 确保为监视用户使用其他角色。 请记住,身份验证和授权是分离的。 这意味着访问/监视仅受用户角色的限制,而不受用户身份验证的方式的限制。 在当前设置下,用户可以向ldap AuthenticationManager进行身份验证,如果为他们分配了角色“ ROLE_USER”,则他们可以访问/ monitoring并查看该URL。
  • 虽然不是必需的,但我们会更新第一个<http>的拦截URL以在每个URL上都匹配。 因为第一个<http>首先仅用于/ monitoring URL,所以这不是必需的,但是如果以后有人更新了pattern属性,这会更安全一些。

更改示例如下:

<http authentication-manager-ref="internal" pattern="/monitoring">    
    <intercept-url pattern="/**" access="ROLE_MONITORING" />
    <http-basic />
</http>

<http authentication-manager-ref="ldap" auto-config='true' use-expressions="true">
    <intercept-url pattern="/**" access="permitAll" />
    <form-login login-page='/' default-target-url='/login_ok'
        always-use-default-target='true' authentication-failure-url="/login_failed" />
    <logout logout-success-url="/" />
</http>

<authentication-manager id="internal">
   <authentication-provider>
       <user-service>
       <user name="monitoring" password="monitoring" authorities="ROLE_MONITORING" />
       </user-service>
   </authentication-provider>
</authentication-manager>

<authentication-manager erase-credentials="false" id="ldap">
    <ldap-authentication-provider
        group-search-filter="${ldap.group-search-filter}" server-ref="ldapServer"
        group-search-base="${ldap.group-search-base}" user-search-filter="${ldap.user-search-filter}"
        user-search-base="${ldap.user-search-base}" group-role-attribute="${ldap.group-role-attribute}"
        role-prefix="${ldap.role-prefix}">
    </ldap-authentication-provider>
    <authentication-provider user-service-ref="userService" />
</authentication-manager>

我要考虑的一件事是将监视用户迁移到LDAP。 将此用户放置在内存中的实例会鼓励不再维护该用户(即应定期旋转密码)。 这还将确保您在LDAP用户和内部用户之间不会发生任何冲突(即,您如何知道ldap身份验证中没有名为“ monitoring”的用户?)。 最后,它简化了您的配置,您只需要单个<http>配置。 如果存在HTTP Basic标头,它仍将使用它进行身份验证。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM