获取和验证Windows AD域的用户信息
1、获取windows AD域用户信息,首先需要有一个ad域管理员权限的账号,用这个账号连接ad域,获取所有域用户信息
用LdapContext,它继承自DirContext
public Object getAllAdUserNames() { List<String> list = new ArrayList<>(); String username = "lisi@ad.com"; String password = "123@abc.com"; String url = "ldap://192.168.44.40:389"; //使用ldap协议连接windows ad域,缺省端口是389 Hashtable env = new Hashtable(); env.put(Context.SECURITY_AUTHENTICATION, "simple");//"none","simple","strong" env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, url); env.put(Context.SECURITY_PRINCIPAL, username); env.put(Context.SECURITY_CREDENTIALS, password); NamingEnumeration results = null; try { LdapContext ctx = new InitialLdapContext(env,null); SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); String searchFilter = "(&(objectCategory=person)(objectClass=user)(name=*))"; String searchBase = "DC=ad,DC=com"; // String returnedAtts[] = {"memberOf"};
//获取登录名,samaccountname是兼容windows2000以前系统的(如:lisi),userprincipalname是带域名的登录名(如:lisi@ad.com)
String returnedAtts[] = {"samaccountname", "userprincipalname"}; searchControls.setReturningAttributes(returnedAtts); NamingEnumeration<SearchResult> result = ctx.search(searchBase,searchFilter,searchControls); while (result.hasMoreElements()) { SearchResult searchResult = (SearchResult) result.next(); list.add(searchResult.getName()); System.out.println("[" + searchResult.getName() + "]"); } ctx.close(); } catch (AuthenticationException e) { e.printStackTrace(); return e.toString(); } catch (NameNotFoundException e) { e.printStackTrace(); return e.toString(); } catch (NamingException e) { e.printStackTrace(); return e.toString(); } finally { if (results != null) { try { results.close(); } catch (Exception e) { } } } return list; }
2、用DirContext,与上边略有区别
public List<String> getAllPersonNames() { String username = "lisi@ad.com"; String password = "123@abc.com"; Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://192.168.44.40:389/dc=ad,dc=com"); env.put(Context.SECURITY_PRINCIPAL, username); env.put(Context.SECURITY_CREDENTIALS, password); DirContext ctx; try { ctx = new InitialDirContext(env); } catch (NamingException e) { throw new RuntimeException(e); } List<String> list = new ArrayList<>(); NamingEnumeration<SearchResult> results = null; try { SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); String searchFilter = "(&(objectCategory=person)(objectClass=user)(name=*))"; results = ctx.search("", searchFilter, controls); while (results.hasMoreElements()) { SearchResult searchResult = results.next(); Attributes attributes = searchResult.getAttributes(); Attribute attr = attributes.get("cn"); String cn = attr.get().toString(); list.add(cn); } } catch (NameNotFoundException e) { e.printStackTrace(); } catch (NamingException e) { e.printStackTrace(); } finally { if (results != null) { try { results.close(); } catch (Exception e) { // Never mind this. } } if (ctx != null) { try { ctx.close(); } catch (Exception e) { // Never mind this. } } } return list; }
3、用Spring集成ldap
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
application.yml的配置,一种方式自定义ldap,一种是直接采用spring data集成
3.1自定义,重载LdapTemplate
application.yml
#自定义的ldap config ldap: base: OU=开发部,DC=ad,DC=com url: "ldap://192.168.44.40:389" username: xu.dm@ad.com password: "123@abc.com" referral: follow
LdapConfig,referral参数具体含义不明确,可以注销了
@Configuration public class LdapConfig { @Value("${ldap.url}") private String ldapUrl; @Value("${ldap.base}") private String ldapBase; @Value("${ldap.username}") private String ldapUserDn; @Value("${ldap.password}") private String ldapUserPwd; @Value("${ldap.referral}") private String ldapReferral; @Bean public LdapTemplate ldapTemplate() { return new LdapTemplate(contextSourceTarget()); } @Bean public LdapContextSource contextSourceTarget() { LdapContextSource ldapContextSource = new LdapContextSource(); ldapContextSource.setUrl(ldapUrl); ldapContextSource.setBase(ldapBase); ldapContextSource.setUserDn(ldapUserDn); ldapContextSource.setPassword(ldapUserPwd); // ldapContextSource.setReferral(ldapReferral); ldapContextSource.setPooled(false); ldapContextSource.afterPropertiesSet(); return ldapContextSource; } }
@Service public class LdapServiceImpl implements LdapService { @Resource LdapTemplate ldapTemplate; @Override public Iterable<User> getUserList(String cn) { LdapQuery query = LdapQueryBuilder.query().attributes("cn").where("objectclass") .is("user").and("cn").is(cn); return ldapTemplate.find(query,User.class); } @Override public User create(User user) { ldapTemplate.create(user); return user; } @Override public void delete(User user) { ldapTemplate.delete(user); } } @Override public Iterable<User> findAll() { return ldapTemplate.findAll(User.class); } }
实体:
@Entry(base = "dc=ad,dc=com", objectClasses = {"top","person"}) public class User implements Serializable { @Id @JsonIgnore private Name dn; // @DnAttribute(value = "distiguishedName") // private String distinguishedName; @Attribute(name = "cn") // @DnAttribute(value="cn", index=1) private String commonName; @Attribute(name = "sn") private String suerName; @Attribute(name="userPassword") private String userPassword; // @DnAttribute(value="ou", index=0) @Attribute(name="ou") private String organizaitonUnit; @Attribute(name="displayName") private String displayName; public User() { } public User(String commonName, String organizaitonUnit) { Name dn = LdapNameBuilder.newInstance() .add("ou",organizaitonUnit) .add("cn",commonName) .build(); this.dn = dn; this.commonName = commonName; this.organizaitonUnit = organizaitonUnit; }
。。。 。。。略
}
3.2 Spring data集成方式
application.yml
#spring data方式 spring: ldap: base: OU=开发部,DC=ad,DC=com urls: "ldap://192.168.44.40:389" username: xu.dm@ad.com password: "123@abc.com"
public interface UserRepository extends LdapRepository<User> { }
@Service public class LdapServiceImpl implements LdapService { @Resource UserRepository userRepository; @Override public User findOne(String cn) { LdapQuery query = LdapQueryBuilder.query().attributes("cn").where("objectclass") .is("person").and("cn").is(cn); return userRepository.findOne(query).orElse(null); } }