为Ldap连接配置Spring安全性

我必须配置Spring安全性以通过LDAP对用户进行身份validation。 这是经理用户所在的子树:

ldaps://vldp.floal:636/CN=Administration,CN=fdam,DC=fg,DC=local 

这是用户所在的地方:

 ldaps://vldp.floal:636/CN=ProxyUsers,CN=fdam,DC=fg,DC=local 

所以我使用这个设置:

 @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{ auth.ldapAuthentication() .contextSource() .url("ldaps://vldp.floal:636/DC=fg,DC=local") .managerDn("CN=A0XXX32,CN=Administration,CN=fdam,DC=fg,DC=local") .managerPassword(password) .and() .userSearchBase("CN=ProxyUsers,CN=fdam") .userSearchFilter("(CN={0})") .ldapAuthoritiesPopulator(myAuthPopulator); } 

当我尝试通过用户登录时,问题是exception抛出,我收到此错误:

 2016-03-25 14:43:14 [http-nio-8086-exec-6] ERROR osswaUsernamePasswordAuthenticationFilter - An internal error occurred while trying to authenticate the user. org.springframework.security.authentication.InternalAuthenticationServiceException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031522C9, problem 2001 (NO_OBJECT), data 0, best match of: 'CN=fdam,DC=fg,DC=local' ]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031522C9, problem 2001 (NO_OBJECT), data 0, best match of: 'CN=fdam,DC=fg,DC=local' ]; remaining name 'cn=F67XXX7A,cn=ProxyUsers,cn=fdam' at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:207) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:82) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167) ~[spring-security-core-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:192) ~[spring-security-core-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:93) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:120) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) [spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) [spring-web-4.2.1.RELEASE.jar:4.2.1.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.26] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.26] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [catalina.jar:8.0.26] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.26] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [catalina.jar:8.0.26] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [catalina.jar:8.0.26] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.26] at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) [catalina.jar:8.0.26] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.26] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [catalina.jar:8.0.26] at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat-coyote.jar:8.0.26] at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) [tomcat-coyote.jar:8.0.26] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1526) [tomcat-coyote.jar:8.0.26] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1482) [tomcat-coyote.jar:8.0.26] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_60] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_60] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.26] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_60] Caused by: org.springframework.ldap.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031522C9, problem 2001 (NO_OBJECT), data 0, best match of: 'CN=fdam,DC=fg,DC=local' ]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031522C9, problem 2001 (NO_OBJECT), data 0, best match of: 'CN=fdam,DC=fg,DC=local' ]; remaining name 'cn=F67XXX7A,cn=ProxyUsers,cn=fdam' at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:183) ~[spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE] at org.springframework.security.ldap.authentication.BindAuthenticator.bindWithDn(BindAuthenticator.java:148) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.ldap.authentication.BindAuthenticator.authenticate(BindAuthenticator.java:95) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE] at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:189) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE] ... 41 common frames omitted Caused by: javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031522C9, problem 2001 (NO_OBJECT), data 0, best match of: 'CN=fdam,DC=fg,DC=local' ] at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3160) ~[na:1.8.0_60] at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3081) ~[na:1.8.0_60] at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2888) ~[na:1.8.0_60] at com.sun.jndi.ldap.LdapCtx.c_getAttributes(LdapCtx.java:1329) ~[na:1.8.0_60] at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_getAttributes(ComponentDirContext.java:235) ~[na:1.8.0_60] at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.getAttributes(PartialCompositeDirContext.java:141) ~[na:1.8.0_60] at javax.naming.directory.InitialDirContext.getAttributes(InitialDirContext.java:152) ~[na:1.8.0_60] at org.springframework.security.ldap.authentication.BindAuthenticator.bindWithDn(BindAuthenticator.java:124) ~[spring-security-ldap-4.0.2.RELEASE.jar:4.0.2.RELEASE] ... 43 common frames omitted 

弹簧参数存在问题,因为如果我使用java代码对用户进行身份validation,则可以使用它。 我无法弄清楚问题出在哪里,你能帮助我吗?

我进入调试,这是错误之前的输出:

 2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG ossecurity.web.FilterChainProxy - /login at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG osswumAntPathRequestMatcher - Checking match of request : '/login'; against '/login' 2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG osswaUsernamePasswordAuthenticationFilter - Request is to process authentication 2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG ossauthentication.ProviderManager - Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider 2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG osslaLdapAuthenticationProvider - Processing authentication request for user: F67XXX7A 2016-03-30 11:35:22 [http-nio-8086-exec-6] DEBUG osslsFilterBasedLdapUserSearch - Searching for user 'F67XXX7A', with user search [ searchFilter: '(CN={0})', searchBase: 'CN=fdam', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ] 2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG oslcsAbstractContextSource - Got Ldap context on server 'ldaps://vldp.floal:636/dc=fg,dc=local' 2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG osslSpringSecurityLdapTemplate - Searching for entry under DN 'dc=fg,dc=local', base = 'cn=fdam', filter = '(CN={0})' 2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG osslSpringSecurityLdapTemplate - Found DN: CN=F67XX7A,CN=ProxyUsers,CN=fdam 2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG osslaBindAuthenticator - Attempting to bind as cn=F67XX7A,cn=ProxyUsers,cn=fdam,dc=fg,dc=local 2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG osslDefaultSpringSecurityContextSource - Removing pooling flag for user cn=F67XX7A,cn=ProxyUsers,cn=fdam,dc=fg,dc=local 2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG oslcsAbstractContextSource - Got Ldap context on server 'ldaps://vldp.floal:636/dc=fg,dc=local' 2016-03-30 11:35:23 [http-nio-8086-exec-6] DEBUG osslaBindAuthenticator - Retrieving attributes... 2016-03-30 11:35:23 [http-nio-8086-exec-6] ERROR osswaUsernamePasswordAuthenticationFilter - An internal error occurred while trying to authenticate the user. 

PS:如果使用ldap浏览器,则使用CN=F67XXX7A,CN=ProxyUsers,CN=fdam,DC=fg,DC=local它绑定。

更新 :如果我使用没有Spring登录的java,我需要使用Spring并弄清楚如何配置它:

 @Override public void isAuthenticated(String username, String password) throws LdapException{ if (databaseMatlabClientServices.getByUsersEnabled(username)== null) throw new LdapException("User doesn't exist into DART database. Please contact the administrator!"); String dn="";; //First query to retriev DN Hashtable ldapEnv = new Hashtable(); ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); ldapEnv.put(Context.PROVIDER_URL, env.getRequiredProperty(PROPERTY_NAME_LDAP_URL)); //Without authentication ldapEnv.put(Context.SECURITY_AUTHENTICATION, "none"); //With authentication to access to LDAP server ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); ldapEnv.put(Context.SECURITY_PRINCIPAL, env.getRequiredProperty(PROPERTY_NAME_LDAP_NAME)); ldapEnv.put(Context.SECURITY_CREDENTIALS, env.getRequiredProperty(PROPERTY_NAME_LDAP_PASSWORD)); String[] returnAttribute = {"dn"}; DirContext ctx = null; NamingEnumeration results = null; try { ctx = new InitialDirContext(ldapEnv); SearchControls controls = new SearchControls(); controls.setReturningAttributes(returnAttribute); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); // without authentication on local server String filter = "uid=" + username ; String filter = "CN=" + username ; results = ctx.search(env.getRequiredProperty(PROPERTY_NAME_LDAP_USERSEARCHBASE), filter, controls); if (results.hasMore()) dn = results.nextElement().getNameInNamespace(); else throw new LdapException("Wrong username. Please retry!"); } catch (NamingException e) { throw new LdapException(e); } finally { try{ if (results != null) results.close(); if (ctx != null) ctx.close(); }catch(Exception e){ throw new LdapException(e); } } //Second query to try to access with obtained Dn and given password Hashtable authEnv = new Hashtable(); authEnv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); authEnv.put(Context.PROVIDER_URL, env.getRequiredProperty(PROPERTY_NAME_LDAP_URL)); authEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); authEnv.put(Context.SECURITY_PRINCIPAL, dn); authEnv.put(Context.SECURITY_CREDENTIALS, password); DirContext ctx2 = null; try { ctx2 = new InitialDirContext(authEnv); } catch (AuthenticationException authEx) { throw new LdapException("Authentication error. Password was wrong"); } catch(Exception e){ throw new LdapException(e); }finally { try{ if (ctx2 != null) ctx2.close(); }catch(Exception e){ throw new LdapException(e); } } } 

更新@pczeus代码 :设置referral = follow我使用过这段代码:

 DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource("ldaps://vldp.floal:636/"); contextSource.setUserDn("CN=A0XXX32,CN=Administration,CN=fdam,DC=fg,DC=local"); contextSource.setPassword(password); contextSource.setReferral("follow"); contextSource.afterPropertiesSet(); LdapAuthenticationProviderConfigurer ldapAuthenticationProviderConfigurer = auth.ldapAuthentication(); ldapAuthenticationProviderConfigurer .ldapAuthoritiesPopulator(myAuthPopulator) .userSearchFilter("(CN={0},CN=ProxyUsers,CN=fdam,DC=fg,DC=local)") .userSearchBase("") .contextSource(contextSource); 

我收到了经典的例外:

 2016-04-07 09:34:41 [http-nio-8086-exec-4] ERROR osswaUsernamePasswordAuthenticationFilter - An internal error occurred while trying to authenticate the user. org.springframework.security.authentication.InternalAuthenticationServiceException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031001E5, problem 2001 (NO_OBJECT), data 0, best match of: '' ]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-031001E5, problem 2001 (NO_OBJECT), data 0, best match of: '' ]; remaining name '/' 

如果我添加.userSearchBase("CN=ProxyUsers,CN=fgadam,DC=fg,DC=local")我收到

 2016-04-07 10:32:56 [http-nio-8086-exec-4] DEBUG osslsFilterBasedLdapUserSearch - Searching for user 'F6XXX7A', with user search [ searchFilter: '(CN={0},CN=ProxyUsers,CN=fdam,DC=fg,DC=local)', searchBase: 'CN=ProxyUsers,CN=fdam,DC=fg,DC=local', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ] 2016-04-07 10:32:57 [http-nio-8086-exec-4] DEBUG oslcsAbstractContextSource - Got Ldap context on server 'ldaps://vldp.floal:636/' 2016-04-07 10:32:57 [http-nio-8086-exec-4] DEBUG osslSpringSecurityLdapTemplate - Searching for entry under DN '', base = 'cn=ProxyUsers,cn=fdam,dc=fg,dc=local', filter = '(CN={0},CN=ProxyUsers,CN=fdam,DC=fg,DC=local)' 2016-04-07 10:32:57 [http-nio-8086-exec-4] DEBUG osswaUsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials 

DN是”,为什么?

在AbstractContextSource(LdapContextSource的父级)中,setBase()方法的Javadoc说明如下:“设置所有操作应该来源的基本后缀。如果设置了基本后缀,则不必(并且确实必须) not)在执行的任何操作中指定完整的专有名称。“ 由于您为userDN / filter指定了完整DN,因此您不能指定基数。

尝试将userSearchBase设置为空字符串(“”),或删除所有userSearchBase调用。

 @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{ auth.ldapAuthentication() .contextSource() .url("ldaps://vldp.floal:636/DC=fg,DC=local") .managerDn("CN=A0XXX32,CN=Administration,CN=fdam,DC=fg,DC=local") .managerPassword(password) .and() .userSearchBase("") .userSearchFilter("CN={0},CN=ProxyUsers,CN=fdam,DC=fg,DC=local") .ldapAuthoritiesPopulator(myAuthPopulator); } 

我们有一个使用Spring Security 3.2.5的遗留应用程序。 我们仍然使用XML来配置它。 也许我的配置可以帮助您识别与您的一切。

我注意到你的userSearchBase不使用完整的“FQDN”。 尝试使用userSearchBase("CN=ProxyUsers,CN=fdam,DC=fg,DC=local") (尽管log msg“ 尝试绑定为cn = F67XX7A,cn = ProxyUsers,cn = fdam,dc = fg,dc =当地的 “)。

另一个提示是使用LDAP浏览器工具导航到ldap服务器并检查CN,DN和OU是否正常。