DefaultLdapAuthoritiesPopulator不授予权限

时间:2013-12-06 23:02:05

标签: spring-security openldap

我正在设置Spring Security以使用LDAP。当Spring的org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator试图为用户获取权限时,我遇到的问题是“无效的DN”错误。我查看了本网站上的其他帖子和其他帖子,但没有任何帮助。我猜我忽略了一些但不知道是什么。

这是错误:

org.springframework.dao.DataAccessResourceFailureException: Failed to borrow DirContext from pool.; nested exception is org.springframework.ldap.InvalidNameException: [LDAP: error code 34 - invalid DN]; nested exception is javax.naming.InvalidNameException: [LDAP: error code 34 - invalid DN]
at org.springframework.ldap.pool.factory.PoolingContextSource.getContext(PoolingContextSource.java:425)
at org.springframework.ldap.pool.factory.PoolingContextSource.getReadWriteContext(PoolingContextSource.java:408)
at org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy.getReadWriteContext(TransactionAwareContextSourceProxy.java:94)
at org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy.getReadOnlyContext(TransactionAwareContextSourceProxy.java:65)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:287)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:259)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:606)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:524)
at org.springframework.security.ldap.SpringSecurityLdapTemplate.searchForSingleAttributeValues(SpringSecurityLdapTemplate.java:173)
at org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator.getGroupMembershipRoles(DefaultLdapAuthoritiesPopulator.java:215)
at org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator.getGrantedAuthorities(DefaultLdapAuthoritiesPopulator.java:185)
at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.loadUserAuthorities(LdapAuthenticationProvider.java:197)
at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:63)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.channel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:144)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:726)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206)
at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:648)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
Caused by: org.springframework.ldap.InvalidNameException: [LDAP: error code 34 - invalid DN]; nested exception is javax.naming.InvalidNameException: [LDAP: error code 34 - invalid DN]
at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:128)
at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:266)
at org.springframework.ldap.core.support.AbstractContextSource.getContext(AbstractContextSource.java:106)
at org.springframework.ldap.core.support.AbstractContextSource.getReadWriteContext(AbstractContextSource.java:138)
at org.springframework.ldap.pool.factory.DirContextPoolableObjectFactory.makeObject(DirContextPoolableObjectFactory.java:127)
at org.apache.commons.pool.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:797)
at org.springframework.ldap.pool.factory.PoolingContextSource.getContext(PoolingContextSource.java:422)
... 41 more
Caused by: javax.naming.InvalidNameException: [LDAP: error code 34 - invalid DN]
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3008)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2815)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2729)
at com.sun.jndi.ldap.LdapCtx.(LdapCtx.java:296)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.init(InitialContext.java:223)
at javax.naming.ldap.InitialLdapContext.(InitialLdapContext.java:134)
at     org.springframework.ldap.core.support.LdapContextSource.getDirContextInstance(LdapContextSource.java:43)
at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:254)
... 46 more

我的ldap服务器版本是OpenLDAP:slapd 2.4.23。我使用的弹簧版本是3.1.4.RELEASE。这些是我的pom.xml文件中的security / ldap依赖项。

<dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-ldap</artifactId>
        <version>${spring.version}</version>
    </dependency> 
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>${spring.version}</version>
    </dependency> 
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>${spring.version}</version>
    </dependency>
            <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap-core</artifactId>
        <version>1.3.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap-core-tiger</artifactId>
        <version>1.3.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap-odm</artifactId>
        <version>1.3.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap-ldif-core</artifactId>
        <version>1.3.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ldap</groupId>
        <artifactId>spring-ldap-ldif-batch</artifactId>
        <version>1.3.1.RELEASE</version>
    </dependency>

这是我的security-context.xml。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-3.1.xsd">    

<bean id="configurer" class="com.bamnetworks.ooo.util.EnvPlaceholderConfigurer" />

<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
    <property name="contextSource" ref="contextSource"/>
</bean>

<bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">
    <property name="url" value="${admin.portal.ldap.url}"/>
    <property name="userDn" value="${admin.portal.ldap.userDn}"/>
    <property name="base" value="${admin.portal.ldap.base}" />
    <property name="password" value="${admin.portal.ldap.password}"/>
    <property name="pooled" value="false"/>
</bean>

<bean id="pooledContextSource" class="org.springframework.ldap.pool.factory.PoolingContextSource">
    <property name="contextSource" ref="contextSourceTarget"/>
    <property name="dirContextValidator" ref="dirContextValidator"/>
    <!-- property name="testOnBorrow" value="true"/ -->
    <!-- property name="testWhileIdle" value="true"/ -->
    <property name="minIdle" value="${admin.portal.ldap.minIdle}"/>
    <property name="maxIdle" value="${admin.portal.ldap.maxIdle}"/>
    <property name="maxActive" value="${admin.portal.ldap.maxActive}"/>
    <property name="maxTotal" value="${admin.portal.ldap.maxTotal}"/>
    <property name="maxWait" value="${admin.portal.ldap.maxWait}"/>
</bean>

<bean id="contextSource"
      class="org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy">
    <constructor-arg ref="pooledContextSource"/>
</bean>

<bean id="dirContextValidator"
      class="org.springframework.ldap.pool.validation.DefaultDirContextValidator"/>


<bean id="ldapAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
 <constructor-arg>
   <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
     <constructor-arg ref="contextSourceTarget"/>
     <property name="userDnPatterns">
       <list><value>cn={0},ou=user</value></list>
     </property>
   </bean>
 </constructor-arg>
 <constructor-arg>
   <bean
     class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
     <constructor-arg index="0" ref="contextSource"/>
     <constructor-arg index="1" value="ou=user,dc=company,dc=com"/>
     <property name="groupRoleAttribute" value="ou"/>
     <property name="searchSubtree" value="true"/>
     <property name="rolePrefix" value="ROLE_"/>
     <property name="convertToUpperCase" value="true"/>
     <property name="groupSearchFilter" value="(&amp;(member={0}))"/>
   </bean>
 </constructor-arg>
</bean>

<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
    <constructor-arg>
        <list>
            <ref local="ldapAuthenticationProvider" />
        </list>
    </constructor-arg>
</bean>

<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
 <property name="loginFormUrl" value="/login.html"/>
</bean>

<bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
  <property name="errorPage" value="/login.html"/>
</bean>

<bean id="form_login_filter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="filterProcessesUrl" value="/login/process"/>
</bean>

<security:http pattern="/admin_portal/css/**" security="none"/>
<security:http pattern="/admin_portal/images/**" security="none"/>
<security:http auto-config="false" 
                authentication-manager-ref="authenticationManager" 
                entry-point-ref="authenticationEntryPoint" 
                access-denied-page="/login.html">
    <security:intercept-url pattern="/login.html*" requires-channel="http" access="ROLE_ANONYMOUS"/>
    <security:intercept-url pattern="/login/process" requires-channel="http" access="ROLE_ANONYMOUS"/>
    <security:intercept-url pattern="/search.html*" requires-channel="http" access="ROLE_ACME_ADMIN"/>
    <security:intercept-url pattern="/ws/**" requires-channel="http" access="ROLE_ACME_ADMIN"/>
    <security:custom-filter position="FORM_LOGIN_FILTER" ref="form_login_filter" />
</security:http>

</beans>

这是我(暂时)的简单登录页面。

<form method="POST" action="/admin_portal/login/process">
   Username: <input type="text" name="j_username" size="15" /><br />
   Password: <input type="password" name="j_password" size="15" /><br />
   <div align="center">
       <p><input type="submit" value="Login" /></p>
   </div>
</form>

这些是LDAP中的对象:

 # user, company.com
 dn: ou=user,dc=company,dc=com
 ou: user
 objectClass: organizationalUnit

 # ACME_ADMIN, user, company.com
 dn: cn=ACME_ADMIN,ou=user,dc=company,dc=com
 cn: ACME_ADMIN
 objectClass: groupOfNames
 objectClass: top
 ou: ACME_ADMIN
 member: cn=LucyVanPelt,ou=user,dc=company,dc=com

 # LucyVanPelt, user, company.com
 dn: cn=LucyVanPelt,ou=user,dc=company,dc=com
 givenName: Lucy
 sn: VanPelt
 userPassword:: MTIzNDU=
 uidNumber: 1002
 gidNumber: 500
 homeDirectory: /home/users/lvanpelt
 loginShell: /bin/sh
 objectClass: inetOrgPerson
 objectClass: posixAccount
 objectClass: top
 cn: LucyVanPelt
 ou: ACME_ADMIN
 uid: LucyVanPelt

当我在命令行上运行此搜索时。

/usr/bin/ldapsearch -x -b "ou=user,dc=company,dc=com" -D "cn=Manager,dc=company,dc=com" -w xxxxxxxxx "(&(member=cn=LucyVanPelt,ou=user,dc=company,dc=com))"

我得到了这个结果:

# ACME_ADMIN, user, company.com
dn: cn=ACME_ADMIN,ou=user,dc=company,dc=com
cn: ACME_ADMIN
objectClass: groupOfNames
objectClass: top
ou: ACME_ADMIN
member: cn=LucyVanPelt,ou=user,dc=company,dc=com

This is some debugging output in the log files: 2013-12-06 10:57:43,831 [btpool0-0] DEBUG AntPathRequestMatcher - Checking match of request : '/login/process'; against '/admin_portal/css/**' 2013-12-06 10:57:43,832 [btpool0-0] DEBUG AntPathRequestMatcher - Checking match of request : '/login/process'; against '/admin_portal/images/**' 2013-12-06 10:57:43,833 [btpool0-0] DEBUG FilterChainProxy - /login/process at position 1 of 9 in additional filter chain; firing Filter: 'ChannelProcessingFilter' 2013-12-06 10:57:43,833 [btpool0-0] DEBUG AntPathRequestMatcher - Checking match of request : '/login/process'; against '/login.html*' 2013-12-06 10:57:43,834 [btpool0-0] DEBUG AntPathRequestMatcher - Checking match of request : '/login/process'; against '/login/process' 2013-12-06 10:57:43,834 [btpool0-0] DEBUG ChannelProcessingFilter - Request: FilterInvocation: URL: /login/process; ConfigAttributes: [REQUIRES_INSECURE_CHANNEL] 2013-12-06 10:57:43,836 [btpool0-0] DEBUG FilterChainProxy - /login/process at position 2 of 9 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 2013-12-06 10:57:43,836 [btpool0-0] DEBUG HttpSessionSecurityContextRepository - No HttpSession currently exists 2013-12-06 10:57:43,836 [btpool0-0] DEBUG HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created. 2013-12-06 10:57:43,839 [btpool0-0] DEBUG FilterChainProxy - /login/process at position 3 of 9 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 2013-12-06 10:57:43,839 [btpool0-0] DEBUG UsernamePasswordAuthenticationFilter - Request is to process authentication 2013-12-06 10:57:43,846 [btpool0-0] DEBUG ProviderManager - Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider 2013-12-06 10:57:43,853 [btpool0-0] DEBUG LdapAuthenticationProvider - Processing authentication request for user: LucyVanPelt 2013-12-06 10:57:43,861 [btpool0-0] DEBUG BindAuthenticator - Attempting to bind as cn=LucyVanPelt,ou=user,dc=company,dc=com 2013-12-06 10:57:44,149 [btpool0-0] DEBUG AbstractContextSource - Got Ldap context on server 'ldap://m1devldap01.mm3.company.com:389/dc=company,dc=com' 2013-12-06 10:57:44,153 [btpool0-0] DEBUG BindAuthenticator - Retrieving attributes... 2013-12-06 10:57:44,265 [btpool0-0] DEBUG DefaultLdapAuthoritiesPopulator - Getting authorities for user cn=LucyVanPelt,ou=user,dc=company,dc=com 2013-12-06 10:57:44,265 [btpool0-0] DEBUG DefaultLdapAuthoritiesPopulator - Searching for roles for user 'LucyVanPelt', DN = 'cn=LucyVanPelt,ou=user,dc=company,dc=com', with filter (&(member={0})) in search base 'ou=user,dc=company,dc=com' 2013-12-06 10:57:44,266 [btpool0-0] DEBUG SpringSecurityLdapTemplate - Using filter: (&(member=cn=LucyVanPelt,ou=user,dc=company,dc=com)) 2013-12-06 10:57:44,266 [btpool0-0] INFO LdapTemplate - The returnObjFlag of supplied SearchControls is not set but a ContextMapper is used - setting flag to true 2013-12-06 10:57:44,273 [btpool0-0] DEBUG DirContextPoolableObjectFactory - Creating a new READ_WRITE DirContext

看起来Spring使用与命令行中使用ldapsearch工具时相同的过滤器和搜索库。它适用于该工具。不知道Spring Tho我缺少什么。任何帮助是极大的赞赏。

由于 雪

1 个答案:

答案 0 :(得分:0)

在我的配置文件中,我在管理员用户dn周围有额外的引号,这使得它无效。很奇怪,BindAuthenticator没有问题。