1

我正在尝试同时启用 JDBA 和 Active Directory 身份验证,我取得了很大进展,但目前我陷入困境,因为 userDetailsS​​ervice 正在尝试比较 LdapUserDetails 中不存在的密码。检查日志时,我看到它能够查询用户并进行身份验证并正确获取角色。

我知道我应该使用 bindService 左右,但直到现在我才找到如何做到这一点。

下面是我所做的。

在 WebSecurityConfigurerAdapter

@Autowired
public void configureGlobal(UserDetailsService userDetailsService,UserLdapRepositoryUserDetailsService userLdapRepositoryUserDetailsService,AuthenticationManagerBuilder auth) throws Exception {
    auth
        .userDetailsService(userDetailsService).
    and()
        .userDetailsService(userLdapRepositoryUserDetailsService);
}

对于 LDAP 配置

    @Bean
public BaseLdapPathContextSource contextSource() {
    DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource("ldap://XXXXX:389/dc=XXXXXX,dc=co");
    //contextSource.setUserDn("CN=Ali Shahbour,OU=Users,DC=XXXXXXX,DC=co");
    contextSource.setUserDn("XXXXXX");
    contextSource.setPassword("XXXXXX");
    return contextSource;
}

@Bean
@Autowired
public LdapUserSearch userSearch(BaseLdapPathContextSource contextSource) { 
    FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch("", "(uid={0})", contextSource);
    return userSearch;
}

@Bean 
@Autowired
public LdapAuthoritiesPopulator authoritiesPopulator(BaseLdapPathContextSource contextSource) {

    DefaultLdapAuthoritiesPopulator authoritiesPopulator = new DefaultLdapAuthoritiesPopulator(contextSource, "OU=CDRMonitor");

    authoritiesPopulator.setGroupSearchFilter("(member={0})");
    //authoritiesPopulator.setRolePrefix("ROLE");
    authoritiesPopulator.setSearchSubtree(true);
    //authoritiesPopulator.setConvertToUpperCase(true);

    return authoritiesPopulator;
}

至于 LdapUserDetailsS​​ervice

@Service("userLdapRepositoryUserDetailsService")
public class UserLdapRepositoryUserDetailsService extends LdapUserDetailsService {

private final UserRepository userRepository;

@Autowired
public UserLdapRepositoryUserDetailsService(LdapUserSearch userSearch,
        LdapAuthoritiesPopulator authoritiesPopulator,UserRepository userRepository) {
    super(userSearch, authoritiesPopulator);
    this.userRepository = userRepository;


}

@Override
public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException {
    UserDetails userDetails = super.loadUserByUsername(username);
    //User user = userRepository.findByEmail(username);
    User user = new User();
    return new LdapUserRepositoryUserDetails(user, userDetails);
}

@Override
public void setUserDetailsMapper(UserDetailsContextMapper userDetailsMapper) {
    super.setUserDetailsMapper(userDetailsMapper);
}

private final static class LdapUserRepositoryUserDetails extends User implements LdapUserDetails {

    private final LdapUserDetailsImpl ldapUserDetailsImpl;

    private LdapUserRepositoryUserDetails(User user,UserDetails userDetails) {
        super(user);
        ldapUserDetailsImpl = (LdapUserDetailsImpl) userDetails;
    }

    private static final long serialVersionUID = 5639683223516504866L;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return ldapUserDetailsImpl.getAuthorities();
    }

    @Override
    public String getUsername() {
        // TODO Auto-generated method stub
        return ldapUserDetailsImpl.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return ldapUserDetailsImpl.isAccountNonExpired();
    }

    @Override
    public boolean isAccountNonLocked() {
        return ldapUserDetailsImpl.isAccountNonLocked();
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return ldapUserDetailsImpl.isCredentialsNonExpired();
    }

    @Override
    public boolean isEnabled() {
        return ldapUserDetailsImpl.isEnabled();
    }

    @Override
    public String getDn() {
        return ldapUserDetailsImpl.getDn();
    }
}

}

4

1 回答 1

0

身份验证上下文中的 LDAP 和 SQL 通常不一起使用,因为 LDAP BIND 身份验证将密码发送到 LDAP 服务器,而不是检索密码的哈希值。

LDAP 身份验证的预期过程如下:

  • 通常使用 spring security UsernamePassword 过滤器来获取凭据,并且默认情况下处于活动状态。例如,如果您使用登录表单,则在提交表单时,此过滤器会获取凭据。
  • 接下来,LDAP 身份验证提供程序对 LDAP 服务器 (LDAP ContextSource) 执行登录 (LDAPBindAuthenticator) 以验证凭据。
  • 如果登录成功,LDAP 身份验证提供程序会在 LDAP 中搜索用户条目。这可以通过提供“用户搜索”spring bean 来定制。
  • 如果找到用户条目,LDAP 权限映射器会将用户条目的属性映射到 spring security 中的组/角色。默认情况下,这是所有 OU 属性
  • 最后,使用用户名和从 LDAP 检索的组创建一个新的身份验证对象。

这里解释了如何使用 Spring XML 集成 LDAP 身份验证。 http://docs.spring.io/spring-security/site/docs/3.1.x/reference/ldap.html

于 2014-05-15T14:21:07.430 回答