メインコンテンツまでスキップ

LDAP認証

このTipは@mleneveutにより提出され @patrickjp93により更新されました。

JHipsterアプリケーションにLDAP認証を追加するには、次の手順に従います。

  • spring-ldap-coreとspring-security-ldapの依存関係を追加します。gradleでのbuild.gradleの例です。
compile group: 'org.springframework.security', name: 'spring-security-ldap', version: spring_security_version
  • SecurityConfiguration.javaを変更し、メソッドconfigureGlobal(AuthenticationManagerBuilder auth)とgetContextSource()を追加します。
  • 次のクエリ文字列は、理想的には環境変数にカプセル化するか、少なくともproperties/ymlファイルにカプセル化する必要があります。
@Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userSearchBase("o=myO,ou=myOu") //ベースを追加しない
.userSearchFilter("(uid={0})")
.groupSearchBase("ou=Groups") //ベースを追加しない
.groupSearchFilter("member={0}")
.contextSource(getContextSource());
}
@Bean
public LdapContextSource getContextSource() {
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl("ldap://[IP goes here]:[port goes here]");
contextSource.setBase("dc=mycompany,dc=com");
contextSource.setUserDn("cn=aUserUid,dc=mycompany,dc=com");
contextSource.setPassword("hisPassword");
contextSource.afterPropertiesSet(); //必要です。さもなければSpringでNullPointerExceptionが発生します。

return contextSource;
}
  • SecurityUtils.javaのメソッドgetCurrentUserLogin()を変更します。
    } else if (authentication.getPrincipal() instanceof LdapUserDetails) {
LdapUserDetails ldapUser = (LdapUserDetails) authentication.getPrincipal();
return ldapUser.getUsername();
}
  • 新しいCustomAuthenticationManagerクラスを追加します。AuthenticationManagerインタフェースを実装し、認証方式をオーバーライドして、認証プロセスがLDAPを介してユーザーを認証を強制するようにします。

@Component
public class CustomAuthenticationManager implements AuthenticationManager {

LdapAuthenticationProvider provider = null;

private static final Logger log = LoggerFactory.getLogger(CustomAuthenticationManager.class);

private final UserRepository userRepository;

@Autowired
private final LdapContextSource ldapContextSource;

public CustomAuthenticationManager(UserRepository userRepository, LdapContextSource ldapContextSource) {
this.userRepository = userRepository;
this.ldapContextSource = ldapContextSource;
}

@Override
public Authentication authenticate(Authentication authentication) {
log.debug("AUTHENTICATION Login" + authentication.getName());
log.debug("AUTHENTICATION Password" + authentication.getCredentials().toString());

BindAuthenticator bindAuth = new BindAuthenticator(ldapContextSource);
FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch(
"", "(uid={0})",
ldapContextSource);
try{
bindAuth.setUserSearch(userSearch);
bindAuth.afterPropertiesSet();
} catch (Exception ex) {
java.util.logging.Logger.getLogger(CustomAuthenticationManager.class.getName()).log(Level.SEVERE, null, ex);
}
provider = new LdapAuthenticationProvider(bindAuth);
provider.setUserDetailsContextMapper(new UserDetailsContextMapper() {
@Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> clctn) {
Optional<User> isUser = userRepository.findOneWithAuthoritiesByLogin(username);
final User user = isUser.get();
Set<Authority> userAuthorities = user.getAuthorities();
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
for(Authority a: userAuthorities){
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(
a.getName());
grantedAuthorities.add(grantedAuthority);
}
return new org.springframework.security.core.userdetails.User(
username, "1" , grantedAuthorities);
}

@Override
public void mapUserToContext(UserDetails ud, DirContextAdapter dca) {

}
});
return provider.authenticate(authentication);
}
}
  • 一部のLDAPサーバでは、次の認証実装の方が成功していますが、ユーザ認証されたユーザをユーザテーブルにマッピングし、ADグループに基づいて権限を設定するには、より多くの作業が必要です。
  • @eugenpMichael Kostewiczの安定したリファレンス実装に感謝します。
public Authentication authenticate(Authentication authentication) {
log.info("Authorizing active directory ldap ....");

Hashtable<String, String> ldapEnv = new Hashtable<>(Map.of(
Context.INITIAL_CONTEXT_FACTORY, this.InitialContextFactory,
Context.PROVIDER_URL, this.ProviderUrl,
Context.SECURITY_AUTHENTICATION, this.SecurityAuthentication,
Context.SECURITY_PRINCIPAL, this.UserDomain + authentication.getPrincipal(),
Context.SECURITY_CREDENTIALS, authentication.getCredentials().toString(),
Context.SECURITY_PROTOCOL, "ssl"
));

try {
ldapContext = new InitialDirContext(ldapEnv);
authentication.setAuthenticated(true);
log.info("Connected and authenticated.");
ldapContext.close();
} catch (Exception e) {
log.error(e.getMessage());
}
return authentication;
}