通过 Active Directory LDAP 使用 Spring-Security 进行身份验证

Posted

技术标签:

【中文标题】通过 Active Directory LDAP 使用 Spring-Security 进行身份验证【英文标题】:Authentication with Spring-Security via Active Directory LDAP 【发布时间】:2020-02-16 06:02:35 【问题描述】:

我无法使用真实的活动目录进行身份验证,让我更好地解释一下我尝试使用 spring.io 提出的示例进行身份验证,没有问题,内部服务启动没有任何问题。 参考https://spring.io/guides/gs/authenticating-ldap/

我尝试通过插入我的活动目录的配置来修改下面的代码,但没有成功。您能否指导我或向我展示一个真实的案例,即在不使用示例中的内部服务的情况下建立真正的连接?我上网查了一下,发现都和官方的例子差不多,没有任何真实案例

@Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth
            .ldapAuthentication()
                .userDnPatterns("uid=0,ou=people")
                .groupSearchBase("ou=groups")
                .contextSource()
                    .url("ldap://localhost:8389/dc=springframework,dc=org")
                    .and()
                .passwordCompare()
                    .passwordEncoder(new LdapShaPasswordEncoder())
                    .passwordAttribute("userPassword");
    

错误显示: LDAP 处理期间发生未分类异常;嵌套异常为 javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr: DSID-0C0907C2,注释:为了执行此操作,必须在连接上成功绑定。,数据 0,v2580

【问题讨论】:

基于 LDAP 的做法是搜索 EntryDN,然后使用找到的 DN 和提供的密码执行身份验证。很奇怪,该指南显示使用 DN 合作伙伴作为首选。只有在极少数情况下,目录信息树才会是“平面”树。密码比较也是不好的做法。 通常也不允许匿名访问生产目录服务器,因此您需要一个“服务帐户”(特殊的 Bind-DN),可用于对目录服务器执行 LDAP 操作。跨度> 【参考方案1】:

我在这里找到了一个样本,这很有用:

https://github.com/sachin-awati/Mojito/tree/master/webapp/src/main/java/com/box/l10n/mojito/security

如果在 Active Directory 查找期间未找到用户 - loadUserByUsername,您可以选择实现UserDetailsContextMapperImpl,它会覆盖mapUserFromContext 以创建UserDetails 对象。

@Component
public class UserDetailsContextMapperImpl implements UserDetailsContextMapper 

    @Override
    public UserDetails mapUserFromContext(DirContextOperations dirContextOperations, String username, Collection<? extends GrantedAuthority> authorities) 

        UserDetails userDetails = null;

        try 
            userDetails = userDetailsServiceImpl.loadUserByUsername(username);

         catch (UsernameNotFoundException e) 
            String givenName = dirContextOperations.getStringAttribute("givenname");
            String surname = dirContextOperations.getStringAttribute("sn");
            String commonName = dirContextOperations.getStringAttribute("cn");

            userDetails = userDetailsServiceImpl.createBasicUser(username, givenName, surname, commonName);
        

        return userDetails;
    

确保您使用的是ActiveDirectoryLdapAuthenticationProvider spring 安全类,因为与其他 LDAP 服务器相比,Active Directory 有自己的细微差别。您可能需要在安全配置类中使用 @EnableGlobalAuthentication 注释,因为您可以有多个 AuthenticationManagerBuilders,这会造成很多混乱。

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 

        ActiveDirectoryLdapAuthenticationProvider adProvider =
                new ActiveDirectoryLdapAuthenticationProvider("domain.com", "ldap://primarydc.domain.com:389");
        adProvider.setConvertSubErrorCodesToExceptions(true);
        adProvider.setUseAuthenticationRequestCredentials(true);
        auth.authenticationProvider(adProvider);

更多细节在这里: https://github.com/spring-projects/spring-security/issues/4324 https://github.com/spring-projects/spring-security/issues/4571

【讨论】:

【参考方案2】:

是的,通过 LDAP 进行身份验证太痛苦了。为了能够对 AD 执行身份验证,您需要使用 ActiveDirectoryLdapAuthenticationProvider。 这是工作示例:

@Override
protected void configure(AuthenticationManagerBuilder auth) 
    ActiveDirectoryLdapAuthenticationProvider adProvider =
            new ActiveDirectoryLdapAuthenticationProvider("domain.com", "ldap://localhost:8389");
    adProvider.setConvertSubErrorCodesToExceptions(true);
    adProvider.setUseAuthenticationRequestCredentials(true);
    auth.authenticationProvider(adProvider);

为了节省您的时间,请阅读以下内容,这非常重要: AD authentication doc

【讨论】:

以上是关于通过 Active Directory LDAP 使用 Spring-Security 进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 LDAP over TLS 对 Active Directory 进行身份验证?

使用 SQL Server 2005 通过 LDAP 访问 Active Directory 角色成员资格

通过 Active Directory LDAP 使用 Spring-Security 进行身份验证

关于 SonarQube 和 Active Directory 之间的简单 Ldap 连接

通过 Spring Security 的 Active Directory 身份验证返回由 LDAP 引起的有效用户的错误凭据:错误代码 49

Spring Security Active Directory LDAP 身份验证错误