【问题标题】:DefaultLdapAuthoritiesPopulator not granting authoritiesDefaultLdapAuthoritiesPopulator 不授予权限
【发布时间】:2013-12-24 11:14:02
【问题描述】:

我正在设置 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。我使用的 spring 版本是 3.1.4.RELEASE。这些是我的 pom.xml 文件的安全/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 中缺少什么。任何帮助是极大的赞赏。

谢谢 雪

【问题讨论】:

  • 我上面配置中的 BindAuthenticator 是 contextSource 而不是 contextSourceTarget btw。

标签: spring-security openldap


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2017-07-06
    • 2021-07-17
    • 1970-01-01
    • 2016-08-24
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多