首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java JNDI 操作 Active Directory (LDAP) 完整增刪改查實戰

     編輯:Java 相關知識

使用標準 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; }
    }
}

關鍵 AD 屬性對照

LDAP 屬性AD 含義備註
sAMAccountName登入帳號 (pre-Windows 2000)唯一、必填
userPrincipalNameUPN 登入帳號 (user@domain)現代登入建議使用
objectClass物件類別user、organizationalUnit 等
cn通用名稱顯示名稱
ou組織單元部門/OU 路徑
memberOf群組隸屬反向連結屬性,唯讀
unicodePwd密碼需 SSL、特殊格式,建議用 ADSI/POWERSHELL

常見問題與解決

  1. 連線失敗:檢查 389 埠通訊、防火牆、AD 服務狀態
  2. 認證失敗:Principal 格式嘗試 CN=Admin,DC=xxx 或 admin@domain
  3. 權限不足:委派控制授權「建立/刪除/修改使用者物件」
  4. 中文亂碼:確保 JVM -Dfile.encoding=UTF-8,DN 中文需 UTF-8 編碼
  5. 分頁查詢:大量資料使用 PagedResultsControl (RFC 2696)

生產環境建議

  • 連線池化:Spring LDAP LdapTemplate / PoolingContextSource
  • SSL 加密:LDAPS:// + 憑證信任庫配置
  • 錯誤碼處理:映射 AD 錯誤碼 (如 0x31 伺服器關閉、0x52D 鎖定)
  • 審計日誌:記錄所有寫操作 DN、操作人、時間
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved