我正在设置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="(&(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我缺少什么。任何帮助是极大的赞赏。
由于 雪
答案 0 :(得分:0)
在我的配置文件中,我在管理员用户dn周围有额外的引号,这使得它无效。很奇怪,BindAuthenticator没有问题。