如何在java中使用LDAP与数据库?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在java中使用LDAP与数据库?相关的知识,希望对你有一定的参考价值。
我是LDAP
概念及其功能的新手。我在相关网站上阅读了一些关于它的教程并安装Apache Directory Studio
并按照this的说明进行操作。另一方面,我在Java
有一个Spring Boot framework
项目,需要使用LDAP
对用户进行身份验证。我的问题是我不知道如何将我的数据库连接到LDAP
以及这些如何与其他人协作?以及如何从我的LDAP
项目连接到Java
?我在互联网上搜索很多,但我找不到有用的文章甚至是围绕这些问题的样本。
答案
您的数据库与LDAP无关。 Spring有KerberosAuthenticationProvider,它可以针对LDAP验证用户身份。如果您需要搜索LDAP并查询其他一些数据,则必须手动执行。下面是一些代码,用于从LDAP中检索电子邮件,电话和名称。它只是概念的证明,而不是生产准备。
域test.local的所有设置 - 将其替换为您的域名。同样在krb.conf中设置您的域控制器名称。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider;
import org.springframework.stereotype.Component;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.util.Hashtable;
@Component
public class ExtendedKerberosAuthentificationProvider extends KerberosAuthenticationProvider {
private final static Logger logger = LoggerFactory.getLogger(ExtendedKerberosAuthentificationProvider.class);
@Autowired
private UserService userService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Authentication auth = super.authenticate(authentication);
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken)authentication;
LdapContext ctx = getLdapContext(token.getName(), token.getCredentials().toString());
if(ctx!= null){
String phone = loadPhoneFromLDAP(token.getName(), ctx);
if(phone != null){
UserDetails details = userService.loadUserByUsername(token.getName());
UserService.User user = (UserService.User) details;
user.getAccount().setPhone(phone);
UsernamePasswordAuthenticationToken output = new UsernamePasswordAuthenticationToken(user, auth.getCredentials(), user.getAuthorities());
output.setDetails(authentication.getDetails());
output.eraseCredentials();
return output;
}else {
throw new UsernameNotFoundException("Phone not found in AD for user :" + token.getName());
}
}else{
throw new UsernameNotFoundException("Cannot create AD naming context, but user was authenticated with Kerberos");
}
}
public LdapContext getLdapContext(String user, String password){
try{
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "Simple");
env.put(Context.SECURITY_PRINCIPAL, user + "@" + Constants.DOMAIN.toUpperCase());
env.put(Context.SECURITY_CREDENTIALS, password);
env.put(Context.REFERRAL, "follow");
env.put(Context.PROVIDER_URL, "ldap://" +Constants.DOMAIN + ":389");
logger.debug("Attempting to connect to AD...");
LdapContext ctx = new InitialLdapContext(env, null);
logger.debug("Connection Successful.");
return ctx;
}catch(NamingException ex){
logger.error("LDAP Connection: FAILED", ex);
return null;
}
}
private String loadPhoneFromLDAP(String username, LdapContext ctx) {
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
String[] attrIDs = {
"mobile",
"mail",
"canonicalName"};
constraints.setReturningAttributes(attrIDs);
NamingEnumeration answer = ctx.search("DC=test,DC=local",
"(&(objectCategory=person)(objectClass=user)(sAMAccountName="+ username +"))", constraints);
String phone = null;
if (answer.hasMore()) {
Attributes attrs = ((SearchResult) answer.next()).getAttributes();
logger.debug(attrs.get("mail").toString());
logger.debug(attrs.get("mobile").toString());
logger.debug(attrs.get("canonicalName").toString());
phone = (String) attrs.get("mobile").get();
}else{
logger.error("user not found");
}
return phone;
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
return null;
}
}
}
import ExtendedKerberosAuthentificationProvider;
import UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.kerberos.authentication.sun.GlobalSunJaasKerberosConfig;
import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient;
@Configuration
@ImportResource(value = "classpath:spring-security-context.xml")
class SecurityConfig {
@Autowired
public UserService userService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public GlobalSunJaasKerberosConfig globalSunJaasKerberosConfig(){
GlobalSunJaasKerberosConfig globalSunJaasKerberosConfig = new GlobalSunJaasKerberosConfig();
globalSunJaasKerberosConfig.setDebug(true);
globalSunJaasKerberosConfig.setKrbConfLocation("<path to krb.conf>");
return globalSunJaasKerberosConfig;
}
@Bean
public ExtendedKerberosAuthentificationProvider kerberosAuthenticationProvider() {
ExtendedKerberosAuthentificationProvider provider = new ExtendedKerberosAuthentificationProvider();
SunJaasKerberosClient client = new SunJaasKerberosClient();
client.setDebug(true);
provider.setKerberosClient(client);
provider.setUserDetailsService(userService);
return provider;
}
}
=====================
public final static String DOMAIN = "test.local";
krb.conf
[libdefaults]
default_realm = TEST.LOCAL
default_tkt_enctypes = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
default_tgs_enctypes = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
permitted_enctypes = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
[realms]
TEST.LOCAL = {
kdc = <some-server>.test.local
default_domain = TEST.LOCAL
}
[domain_realm]
.test.local = TEST.LOCAL
test.local = TEST.LOCAL
以上是关于如何在java中使用LDAP与数据库?的主要内容,如果未能解决你的问题,请参考以下文章
如何在片段中使用 GetJsonFromUrlTask.java