我试图在我的 mac 上使用 openldap 启动并运行一个 spring 项目。
因为 openldap 默认安装在 OSX 上,我使用那个,然后用 Apache Directory studio 配置它。
我的目录如下所示:
像这样的实体:
当我尝试使用 nilsi 和正确的密码登录时,在 Eclipse 中出现错误:
org.springframework.ldap.NameNotFoundException: [LDAP: error code 32 - No Such Object]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - No Such Object]; remaining name ''
at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:174)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:306)
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.authentication.ProviderManager.authenticate(ProviderManager.java:174)
at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:194)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
在 ldap 控制台中,我得到以下信息:
conn=1000 fd=14 ACCEPT from IP=127.0.0.1:49474 (IP=0.0.0.0:389)
connection_get(14): got connid=1000
connection_read(14): checking for input on id=1000
ber_get_next
ber_get_next: tag 0x30 len 34 contents:
op tag 0x60, time 1360507317
ber_get_next
conn=1000 op=0 do_bind
ber_scanf fmt ({imt) ber:
ber_scanf fmt (m}) ber:
>>> dnPrettyNormal: <ou=users,o=backlog>
<<< dnPrettyNormal: <ou=users,o=backlog>, <ou=users,o=backlog>
conn=1000 op=0 BIND dn="ou=users,o=backlog" method=128
do_bind: version=3 dn="ou=users,o=backlog" method=128
conn=1000 op=0 BIND dn="ou=users,o=backlog" mech=SIMPLE ssf=0
do_bind: v3 bind: "ou=users,o=backlog" to "ou=users,o=backlog"
send_ldap_result: conn=1000 op=0 p=3
send_ldap_response: msgid=1 tag=97 err=0
ber_flush2: 14 bytes to sd 14
conn=1000 op=0 RESULT tag=97 err=0 text=
connection_get(14): got connid=1000
connection_read(14): checking for input on id=1000
ber_get_next
ber_get_next: tag 0x30 len 85 contents:
op tag 0x63, time 1360507317
ber_get_next
conn=1000 op=1 do_search
ber_scanf fmt ({miiiib) ber:
>>> dnPrettyNormal: <ou=users,o=backlog>
<<< dnPrettyNormal: <ou=users,o=backlog>, <ou=users,o=backlog>
ber_scanf fmt ({mm}) ber:
ber_scanf fmt ({M}}) ber:
=> get_ctrls
ber_scanf fmt ({m) ber:
=> get_ctrls: oid="2.16.840.1.113730.3.4.2" (noncritical)
<= get_ctrls: n=1 rc=0 err=""
conn=1000 op=1 SRCH base="ou=users,o=backlog" scope=2 deref=3 filter="(uid=nilsi)"
=> bdb_search
bdb_dn2entry("ou=users,o=backlog")
=> bdb_dn2id("o=backlog")
<= bdb_dn2id: got id=0x8
=> bdb_dn2id("ou=users,o=backlog")
<= bdb_dn2id: got id=0xa
entry_decode: "ou=users,o=backlog"
<= entry_decode(ou=users,o=backlog)
search_candidates: base="ou=users,o=backlog" (0x0000000a) scope=2
=> bdb_equality_candidates (objectClass)
=> key_read
<= bdb_index_read: failed (-30988)
<= bdb_equality_candidates: id=0, first=0, last=0
=> bdb_dn2idl("ou=users,o=backlog")
<= bdb_dn2idl: id=3 first=9 last=11
=> bdb_equality_candidates (uid)
<= bdb_equality_candidates: (uid) not indexed
bdb_search_candidates: id=-1 first=9 last=11
entry_decode: "cn=Knut Knutsson,ou=users,o=backlog"
<= entry_decode(cn=Knut Knutsson,ou=users,o=backlog)
=> bdb_dn2id("cn=knut knutsson,ou=users,o=backlog")
<= bdb_dn2id: got id=0x9
=> send_search_entry: conn 1000 dn="cn=Knut Knutsson,ou=users,o=backlog"
conn=1000 op=1 ENTRY dn="cn=knut knutsson,ou=users,o=backlog"
ber_flush2: 226 bytes to sd 14
<= send_search_entry: conn 1000 exit.
bdb_search: 10 does not match filter
entry_decode: "cn=Mathias Nordin,ou=users,o=backlog"
<= entry_decode(cn=Mathias Nordin,ou=users,o=backlog)
=> bdb_dn2id("cn=mathias nordin,ou=users,o=backlog")
<= bdb_dn2id: got id=0xb
bdb_search: 11 does not match filter
send_ldap_result: conn=1000 op=1 p=3
send_ldap_response: msgid=2 tag=101 err=0
ber_flush2: 14 bytes to sd 14
conn=1000 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
slap_listener_activate(8):
>>> slap_listener(ldap:///)
conn=1001 fd=16 ACCEPT from IP=127.0.0.1:49475 (IP=0.0.0.0:389)
connection_get(16): got connid=1001
connection_read(16): checking for input on id=1001
ber_get_next
ber_get_next: tag 0x30 len 51 contents:
op tag 0x60, time 1360507317
ber_get_next
conn=1001 op=0 do_bind
ber_scanf fmt ({imt) ber:
ber_scanf fmt (m}) ber:
>>> dnPrettyNormal: <cn=Knut Knutsson,ou=users,o=backlog>
<<< dnPrettyNormal: <cn=Knut Knutsson,ou=users,o=backlog>, <cn=knut knutsson,ou=users,o=backlog>
conn=1001 op=0 BIND dn="cn=Knut Knutsson,ou=users,o=backlog" method=128
do_bind: version=3 dn="cn=Knut Knutsson,ou=users,o=backlog" method=128
bdb_dn2entry("cn=knut knutsson,ou=users,o=backlog")
conn=1001 op=0 BIND dn="cn=Knut Knutsson,ou=users,o=backlog" mech=SIMPLE ssf=0
do_bind: v3 bind: "cn=Knut Knutsson,ou=users,o=backlog" to "cn=Knut Knutsson,ou=users,o=backlog"
send_ldap_result: conn=1001 op=0 p=3
send_ldap_response: msgid=1 tag=97 err=0
ber_flush2: 14 bytes to sd 16
conn=1001 op=0 RESULT tag=97 err=0 text=
connection_get(16): got connid=1001
connection_read(16): checking for input on id=1001
ber_get_next
ber_get_next: tag 0x30 len 101 contents:
op tag 0x63, time 1360507317
ber_get_next
conn=1001 op=1 do_search
ber_scanf fmt ({miiiib) ber:
>>> dnPrettyNormal: <cn=Knut Knutsson,ou=users,o=backlog>
<<< dnPrettyNormal: <cn=Knut Knutsson,ou=users,o=backlog>, <cn=knut knutsson,ou=users,o=backlog>
ber_scanf fmt (m) ber:
ber_scanf fmt ({M}}) ber:
=> get_ctrls
ber_scanf fmt ({m) ber:
=> get_ctrls: oid="2.16.840.1.113730.3.4.2" (noncritical)
<= get_ctrls: n=1 rc=0 err=""
conn=1001 op=1 SRCH base="cn=Knut Knutsson,ou=users,o=backlog" scope=0 deref=3 filter="(objectClass=*)"
==> limits_get: conn=1001 op=1 self="cn=knut knutsson,ou=users,o=backlog" this="cn=knut knutsson,ou=users,o=backlog"
=> bdb_search
bdb_dn2entry("cn=knut knutsson,ou=users,o=backlog")
=> send_search_entry: conn 1001 dn="cn=Knut Knutsson,ou=users,o=backlog"
conn=1001 op=1 ENTRY dn="cn=knut knutsson,ou=users,o=backlog"
ber_flush2: 226 bytes to sd 16
<= send_search_entry: conn 1001 exit.
send_ldap_result: conn=1001 op=1 p=3
send_ldap_response: msgid=2 tag=101 err=0
ber_flush2: 14 bytes to sd 16
conn=1001 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
connection_get(16): got connid=1001
connection_read(16): checking for input on id=1001
ber_get_next
ber_get_next: tag 0x30 len 34 contents:
op tag 0x42, time 1360507317
ber_get_next
ber_get_next on fd 16 failed errno=0 (Undefined error: 0)
conn=1001 op=2 do_unbind
conn=1001 op=2 UNBIND
connection_close: conn=1001 sd=16
conn=1001 fd=16 closed
connection_get(14): got connid=1000
connection_read(14): checking for input on id=1000
ber_get_next
ber_get_next: tag 0x30 len 245 contents:
op tag 0x63, time 1360507317
ber_get_next
conn=1000 op=2 do_search
ber_scanf fmt ({miiiib) ber:
>>> dnPrettyNormal: <>
<<< dnPrettyNormal: <>, <>
ber_scanf fmt ({mm}) ber:
>>> nameUIDPretty: <cn=Knut Knutsson,ou=users,o=backlog>
>>> dnPretty: <cn=Knut Knutsson,ou=users,o=backlog>
<<< dnPretty: <cn=Knut Knutsson,ou=users,o=backlog>
<<< nameUIDPretty: <cn=Knut Knutsson,ou=users,o=backlog>
>>> dnNormalize: <cn=Knut Knutsson,ou=users,o=backlog>
<<< dnNormalize: <cn=knut knutsson,ou=users,o=backlog>
ber_scanf fmt ({M}}) ber:
=> get_ctrls
ber_scanf fmt ({m) ber:
=> get_ctrls: oid="2.16.840.1.113730.3.4.2" (noncritical)
<= get_ctrls: n=1 rc=0 err=""
conn=1000 op=2 SRCH base="" scope=2 deref=3 filter="(uniqueMember=cn=knut knutsson,ou=users,o=backlog)"
conn=1000 op=2 SRCH attr=cn objectClass javaSerializedData javaClassName javaFactory javaCodeBase javaReferenceAddress javaClassNames javaRemoteLocation
send_ldap_result: conn=1000 op=2 p=3
send_ldap_response: msgid=3 tag=101 err=32
ber_flush2: 14 bytes to sd 14
conn=1000 op=2 SEARCH RESULT tag=101 err=32 nentries=0 text=
我与 ldap 的连接如下所示:
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/auth/login"
access="permitAll" />
<security:form-login login-page="/auth/login"
authentication-failure-url="/auth/login?error=true" />
<security:logout invalidate-session="true"
logout-success-url="/auth/login" logout-url="/auth/logout" />
</security:http>
<security:ldap-server url="${ldap.url}"
manager-dn="${ldap.managerdn}" manager-password="${ldap.managerpassword}" />
和属性文件:
# Ldap server settings:
ldap.url=ldap://localhost:389
ldap.managerdn=ou=users,o=backlog
ldap.managerpassword=1234
ldap.user-search-filter=(uid={0})
ldap.user-search-base=ou=users,o=backlog
slapd.conf 中的 DBD 定义:
#######################################################################
# BDB database definitions
#######################################################################
database bdb
suffix "o=backlog"
rootdn "ou=users,o=backlog"
# Cleartext passwords, especially for the rootdn, should
# be avoid. See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw {MD5}gdyb21LQTcIANtvYMT7QVQ==
# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory /private/var/db/openldap/backlog
# Indices to maintain
index objectClass eq
但是,当我尝试使用我的 ldap 目录中不存在的帐户登录时,Spring 会以干净的日志和无效的用户名/密码响应进行响应。
此外,如果 ldap 返回以前没有使用过应用程序的用户,应用程序将自动映射具有权限的用户。所以换句话说,如果 ldap 只是返回一个 id/用户名,那么它应该可以工作。