SpringBoot,如何使用LDAP进行身份验证而不使用ldif?

时间:2016-04-20 02:21:08

标签: java spring spring-security spring-boot

我正在尝试SpringBoot here

中的LDAP身份验证示例

我正在使用ldif方法,我认为这不适用于我的要求,因为我们的ldap管理员不会告诉我在哪里可以找到我需要的ldif。 在springboot之前,我曾经使用过自己的ldap实现而不是使用ldif。有没有办法验证不使用ldif只是SECURITY_AUTHENTICATION.simple? 下面是我如何在基本Java没有弹簧的情况下执行ldap安全性。如何在不使用ldif基本用户名密码的情况下在春天这样做。

boolean isLdapRegistred(String username, String password) {
    boolean result = false;
    try {

        Hashtable<String, String> env = new Hashtable<String, String>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldap://10.x.x.x:389");           
        env.put(Context.SECURITY_AUTHENTICATION, "simple");         
        env.put(Context.SECURITY_PRINCIPAL, "OUR-DOMAIN\\" + username);
        env.put(Context.SECURITY_CREDENTIALS, password);

        // Create the initial context
        DirContext ctx = new InitialDirContext(env);
        result = ctx != null;
        if (ctx != null)
        ctx.close();
        System.out.println(result);
        return result;
    } catch (Exception e) {
        System.out.println("oops");
        return result;
    }

}

以下是SpringBoots示例需要使用我的凭据而不是ldif。

@Configuration
protected static class AuthenticationConfiguration extends
        GlobalAuthenticationConfigurerAdapter {

    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .ldapAuthentication()
                .userDnPatterns("uid={0},ou=people")
                .groupSearchBase("ou=groups")
                .contextSource().ldif("classpath:test-server.ldif");
    }
}

3 个答案:

答案 0 :(得分:4)

如果没有LDIF,并且使用Spring,您可以执行以下操作:

@Configuration
@EnableWebSecurity
public class HttpSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(ldapAuthenticationProvider());
    }

    @Bean
    public AuthenticationProvider ldapAuthenticationProvider() throws Exception {
        DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapServerUrl);
        contextSource.setUserDn(ldapManagerDn);
        contextSource.setPassword(ldapManagerPassword);
        contextSource.afterPropertiesSet();
        LdapUserSearch ldapUserSearch = new FilterBasedLdapUserSearch(ldapUserSearchBase, ldapUserSearchFilter, contextSource);
        BindAuthenticator bindAuthenticator = new BindAuthenticator(contextSource);
        bindAuthenticator.setUserSearch(ldapUserSearch);
        LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(bindAuthenticator, new DefaultLdapAuthoritiesPopulator(contextSource, ldapGroupSearchBase));
        return ldapAuthenticationProvider;
    }
}

答案 1 :(得分:3)

这个对我来说很完美,但我需要对它进行微小的修改。

    @Configuration
    @EnableWebSecurity
    public class HttpSecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(ldapAuthenticationProvider());
        }

        @Bean
        public AuthenticationProvider ldapAuthenticationProvider() throws Exception {
            DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(
Arrays.asList("ldapServerUrl:port"),rootDn);
            contextSource.afterPropertiesSet();
            LdapUserSearch ldapUserSearch = new FilterBasedLdapUserSearch(ldapUserSearchBase, ldapUserSearchFilter, contextSource);
            BindAuthenticator bindAuthenticator = new BindAuthenticator(contextSource);
            bindAuthenticator.setUserSearch(ldapUserSearch);
            LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(bindAuthenticator, new DefaultLdapAuthoritiesPopulator(contextSource, ldapGroupSearchBase));
            return ldapAuthenticationProvider;
        }
    }

在达到这一点之前,我已经遭受了好几天的痛苦 另外,您可以使用自定义身份验证并使其像这样

    @Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    private Logger log = Logger.getLogger(CustomAuthenticationProvider.class);

    @Override
    public Authentication authenticate(Authentication authentication) 
      throws AuthenticationException {

        String email = authentication.getName();
        String password = authentication.getCredentials().toString();

        log.info("email : " + email);
        log.info("password : " + password);

        try {
            if (authenticate(email, password)) {

                // use the credentials
                // and authenticate against the third-party system
                return new UsernamePasswordAuthenticationToken(
                        email, password, new ArrayList<>());
            } else {
                return null;
            }
        } catch (NamingException ex) {
            log.info(ex);
        }
        return null;
    }

    boolean isLdapRegistred(String username, String password) {
    boolean result = false;
    try {

        Hashtable<String, String> env = new Hashtable<String, String>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldap://10.x.x.x:389");           
        env.put(Context.SECURITY_AUTHENTICATION, "simple");         
        env.put(Context.SECURITY_PRINCIPAL, "OUR-DOMAIN\\" + username);
        env.put(Context.SECURITY_CREDENTIALS, password);

        // Create the initial context
        DirContext ctx = new InitialDirContext(env);
        result = ctx != null;
        if (ctx != null)
        ctx.close();
        System.out.println(result);
        return result;
    } catch (Exception e) {
        System.out.println("oops");
        return result;
    }

}


    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(
          UsernamePasswordAuthenticationToken.class);
    }
}

和另一个班级

    @Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    private Logger log = Logger.getLogger(WebSecurityConfiguration.class);
    @Autowired
    private CustomAuthenticationProvider authProvider;

    @Override
    protected void configure(
      AuthenticationManagerBuilder auth) throws Exception {

        auth.authenticationProvider(authProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
            .and()
            .httpBasic();
    }
}

然后神奇发生了

答案 2 :(得分:0)

万一有人对相应的Spring Boot配置感兴趣,这对我有用(我试图删除不相关的细节):

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .ldapAuthentication()
                .contextSource()
                .url("ldap://hostname:389/dc=myapp,dc=mycompany,dc=com")
                .and()
                .userDnPatterns("cn={0},cn=Users");
    }
}

上面的代码与以下ldapsearch命令相对应(他们通常建议使用ldapsearch来试用基本DN和userDnPatterns的不同路径配置:

ldapsearch -H "ldap://hostname:389" -D "cn=someuser,cn=Users,dc=myapp,dc=mycompany,dc=com" -W -b "dc=myapp,dc=mycompany,dc=com" 'cn=someuser,cn=Users,dc=myapp,dc=mycompany,dc=com'
  • -W交互式询问密码
  • -H指定host:port
  • -D cn-指示ldapsearch专门绑定到该地址(cn)-据我了解,这相当于使用此CN登录LDAP,只要给以下提示的密码正确就可以了
  • -b ...指定用于过滤结果的基本DN
  • 重要的是不要忘记上面单引号的最后一部分(单引号或双引号,我认为这没有什么不同),因为这指定了ldapsearch在绑定/登录后将执行的查询-如果您不这样做的话如果不指定任何内容,它将尝试执行所有条目的搜索,并可能使LDAP服务器无响应

最后,Spring Boot安全性配置中的{0}是ldapsearch的“ someuser”所在的位置,即Spring将根据userDnPatterns中指定的内容构造要绑定的地址,用登录期间指定的任何用户名替换{0}

PS。这与旧版本的Oracle Internet Directory配合使用,在该版本中,我们要验证的所有用户都位于cn = Users下,而不是例如。 ou =相应的Spring Boot LDAP教程中的人(我想)