简体   繁体   English

Spring Security的许多提供商

[英]Spring Security many providers

In my application I use LDAP authentication (called ldap ). 在我的应用程序中,我使用LDAP身份验证(称为ldap )。 For one of my pages I need my own authentication with basic html popup (called internal ). 对于我的页面之一,我需要使用基本的html弹出窗口(称为internal )进行身份验证。 I get BeanCreationException : 我得到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]

Here is my configuration: 这是我的配置:

<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>

I understand why the exception was thrown and know that patterns order and scopes are important, but have no idea how to do it correctly. 我了解为什么会引发异常,并且知道模式顺序和作用域很重要,但不知道如何正确执行。 All I want, is that every user has access to "/**", but only monitoring user has access to /monitoring (authenticated with basic). 我想要的是,每个用户都可以访问“ / **”, 但是只有监视用户可以访问/ monitoring(已通过基本身份验证)。 Everything worked just fine, before I wanted to add this internal authentication. 在我想添加此内部身份验证之前,一切工作都很好。

The changes you need to make are: 您需要进行的更改是:

  • Ensure to have a pattern for the first <http> . 确保第一个<http>具有模式。 This is the heart of your issue right now. 这是您当前问题的核心。 Both <http> match every request, so the second <http> is never considered. 两个<http>匹配每个请求,因此永远不会考虑第二个<http> To fix this, add the pattern attribute. 要解决此问题,请添加pattern属性。
  • Ensure to use a different role for your monitoring user. 确保为监视用户使用其他角色。 Remember, authentication and authorization are decoupled. 请记住,身份验证和授权是分离的。 This means that accessing /monitoring is only restricted by the role of the user NOT how the user authenticated. 这意味着访问/监视仅受用户角色的限制,而不受用户身份验证的方式的限制。 With the current setup, a user could authenticate to the ldap AuthenticationManager and if they were assigned the role "ROLE_USER" they could then visit /monitoring and see that URL. 在当前设置下,用户可以向ldap AuthenticationManager进行身份验证,如果为他们分配了角色“ ROLE_USER”,则他们可以访问/ monitoring并查看该URL。
  • Although not necessary we update the intercept-url for the first <http> to match on every URL. 虽然不是必需的,但我们会更新第一个<http>的拦截URL以在每个URL上都匹配。 This is not necessary since the first <http> is only used for the /monitoring URL in the first place, but it is a bit safer if someone updated the pattern attribute later on. 因为第一个<http>首先仅用于/ monitoring URL,所以这不是必需的,但是如果以后有人更新了pattern属性,这会更安全一些。

An example of the changes can be seen below: 更改示例如下:

<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>

One thing I would consider is moving the monitoring user into LDAP. 我要考虑的一件事是将监视用户迁移到LDAP。 Placing this user in an in memory instance encourages that user to no longer be maintained (ie password should be rotated regularly). 将此用户放置在内存中的实例会鼓励不再维护该用户(即应定期旋转密码)。 This would also ensure you don't get any collisions between your LDAP users and the internal users (ie how do you know there isn't a user named "monitoring" in the ldap authentication?). 这还将确保您在LDAP用户和内部用户之间不会发生任何冲突(即,您如何知道ldap身份验证中没有名为“ monitoring”的用户?)。 Last it simplifies your configuration, you only need the single <http> configuration. 最后,它简化了您的配置,您只需要单个<http>配置。 If the HTTP Basic header is present, it will still authenticate using it. 如果存在HTTP Basic标头,它仍将使用它进行身份验证。

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

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