使用標準 JNDI API (javax.naming.ldap) 對 Windows AD 域帳號進行 CRUD 操作,含連線認證、搜尋、新增、修改、刪除、重命名完整程式碼。
public class LdapByUser {
private DirContext dc;
private final String root = "DC=2003,DC=com"; // 根 DN
public LdapByUser() { init(); }
private void init() {
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "administrator@2003.com"); // UPN 格式
env.put(Context.SECURITY_CREDENTIALS, "admin");
env.put(Context.PROVIDER_URL, "LDAP://10.10.2.153:389");
try {
dc = new InitialLdapContext(env, null);
System.out.println("認證成功");
} catch (Exception e) {
System.out.println("認證失敗");
e.printStackTrace();
}
}
public void close() {
if (dc != null) try { dc.close(); } catch (NamingException e) { e.printStackTrace(); }
}
// === 搜尋 ===
public SearchResult searchByUserName(String searchBase, String userName) {
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
ctls.setReturningAttributes(new String[]{"memberOf"});
try {
NamingEnumeration<SearchResult> ans = dc.search(searchBase,
"sAMAccountName=" + userName, ctls);
return ans.hasMore() ? ans.next() : null;
} catch (Exception e) { e.printStackTrace(); return null; }
}
public void searchInformation(String searchBase) {
SearchControls ctls = new SearchControls();
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
ctls.setReturningAttributes(new String[]{"memberOf"});
String filter = "(&(objectCategory=person)(objectClass=user)(name=*))";
try {
NamingEnumeration<SearchResult> ans = dc.search(searchBase, filter, ctls);
while (ans.hasMore()) {
SearchResult sr = ans.next();
System.out.println("<<<::[" + sr.getName() + "]::>>>>");
}
} catch (Exception e) { e.printStackTrace(); }
}
// === 新增 ===
public void add(String newUserName) {
try {
BasicAttributes attrs = new BasicAttributes();
BasicAttribute oc = new BasicAttribute("objectClass");
oc.add("sAMAccountName"); oc.add("employeeID");
attrs.put(oc);
attrs.put("ou", newUserName);
dc.createSubcontext("ou=" + newUserName + "," + root, attrs);
} catch (Exception e) { e.printStackTrace(); }
}
// === 刪除 ===
public void delete(String dn) {
try { dc.destroySubcontext(dn); } catch (Exception e) { e.printStackTrace(); }
}
// === 重命名/移動 ===
public boolean renameEntry(String oldDN, String newDN) {
try { dc.rename(oldDN, newDN); return true; }
catch (NamingException e) { System.err.println("Error: " + e.getMessage()); return false; }
}
// === 修改屬性 ===
public boolean modifyInformation(String dn, String employeeID) {
try {
ModificationItem[] mods = new ModificationItem[1];
Attribute attr = new BasicAttribute("OU", employeeID);
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr);
dc.modifyAttributes(dn + ",DC=2003,DC=com", mods);
return true;
} catch (Exception e) { e.printStackTrace(); return false; }
}
}
| LDAP 屬性 | AD 含義 | 備註 |
|---|---|---|
| sAMAccountName | 登入帳號 (pre-Windows 2000) | 唯一、必填 |
| userPrincipalName | UPN 登入帳號 (user@domain) | 現代登入建議使用 |
| objectClass | 物件類別 | user、organizationalUnit 等 |
| cn | 通用名稱 | 顯示名稱 |
| ou | 組織單元 | 部門/OU 路徑 |
| memberOf | 群組隸屬 | 反向連結屬性,唯讀 |
| unicodePwd | 密碼 | 需 SSL、特殊格式,建議用 ADSI/POWERSHELL |
CN=Admin,DC=xxx 或 admin@domain-Dfile.encoding=UTF-8,DN 中文需 UTF-8 編碼PagedResultsControl (RFC 2696)LdapTemplate / PoolingContextSourceLDAPS:// + 憑證信任庫配置