Have you ever want to create a custom login flow with composite of ldap and other authentication? But you relize that, LDAP almost use integrated with Spring security? And you would like to use it seperatedly, yes, me too and now I will share you the way I have used.
1. Use class DefaultSpringSecurityContextSource
to create LDAP context source.
It is a little weird that we will use DefaultSpringSecurityContextSource
to create a LDAP context source. I have tried with LdapContextSource purely, but it is not working! So I switch to use DefaultSpringSecurityContextSource
as source-code of integrated of Spring Security in ldapAuthentication() method :)
private LdapContextSource ldapContextSource() {
final LdapContextSource ldapContextSource = new DefaultSpringSecurityContextSource("YOUR_URL_OF_LDAP");
ldapContextSource.setBase("YOUR_BASE");
ldapContextSource.setUserDn("YOUR_MANAGER_LDAP_USERNAME");
ldapContextSource.setPassword("YOUR_MANAGER_LDAP_PASSWORD");
ldapContextSource.setPooled(true);
return ldapContextSource;
}
with YOUR_URL_OF_LDAP
, sometimes you will need YOUR_URL_OF_LDAP\YOUR_BASE
to get correct url.
2. Define a bean of LDAP Authentication Provider
@Bean
public LdapAuthenticationProvider ldapAuthenticationProvider() {
// use from previous defined method
final LdapContextSource ldapContextSource = ldapContextSource();
final BindAuthenticator bindAuthenticator = new BindAuthenticator(ldapContextSource);
bindAuthenticator.setUserSearch(new FilterBasedLdapUserSearch(
"YOUR_SEARCH_BASE", // if null will search base on baseDn of ldapContextSource
"LDAP_USER_SEARCH_PATTERN",
ldapContextSource)
); // optional
bindAuthenticator.setUserDnPatterns(new String[]{"USER_DN_PATTERN"}); // optional
bindAuthenticator.setUserAttributes(new String[]{"ATTRIBUTE_TO_GET", "mail", "title"}); // optional
final LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(bindAuthenticator);
ldapAuthenticationProvider.setAuthoritiesMapper(username -> {
return new ArrayList<>();
}); // you also can custom for your authority mapper
ldapAuthenticationProvider.setUserDetailsContextMapper(
new InetOrgPersonContextMapper()
); // and you can map user by InetOrgPersonContextMapper to get more info of logon user by ldap
return ldapAuthenticationProvider;
}
That’s Ok, and now, you can put 2 methods in the same class or anywhere you want with annotation @Configuration
to help Spring Boot recognize and initialize it when start up.
3. Use it!
Assume that you created that bean completely, now we will use it in anywhere we want in Spring Boot context, in this case, UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
@Autowired
private LdapAuthenticationProvider ldapAuthenticationProvider;
@Override
public boolean checkLogin(String username, String password){
try {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, password);
final Authentication resultAuthentication = ldapAuthenticationProvider.authenticate(authentication);
// Some other logic, ex: business login, auth2,...
return true; // or result after applied other logics
}catch(Exception ex){
logger.error(ex);
return false;
}
}
}
Yeah, that’s all. Thanks for read the whole article!