Macでopenldapを使用して春のプロジェクトを立ち上げて実行しようとしています。
openldap はデフォルトで OSX im にインストールされているため、それを使用してから 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/ユーザー名を返すだけであれば、それは機能するはずです。