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

封裝 JNDI 操作 LDAP 服務的工具類(五):完整整合測試案例——建立 AD 使用者並啟用帳號

     編輯:Java 相關知識

測試場景

向 Windows Active Directory 新增網域使用者 lwf2_count,並設定密碼、顯示名稱、UPN、sAMAccountName,且啟用帳號(預設建立為停用)。

完整測試代碼

public class TestOper {
    public static void main(String[] args) throws BaseException, NamingException, UnsupportedEncodingException {
        // 1. 連線配置
        Env env = new Env();
        env.factory = "com.sun.jndi.ldap.LdapCtxFactory";
        env.url = "ldap://10.110.179.175:389";
        env.adminUID = "cn=administrator,cn=users,DC=securitytest,DC=boco";
        env.adminPWD = "Ba88736612";

        DirContext dirContext = LdapConnectionFactory.getDirContext(env);
        if (dirContext == null) {
            System.err.println("Failed to connect LDAP");
            return;
        }

        try {
            // 2. 準備使用者屬性
            Map attMap = new HashMap<>();
            List objectClass = Arrays.asList("top", "person", "organizationalPerson", "user");
            attMap.put("objectClass", objectClass);               // 必須:物件類別鏈
            attMap.put("cn", "lwf2_count");                       // 相對辨識名
            attMap.put("sn", "liao");                             // 姓
            attMap.put("givenName", "wufeng");                    // 名
            attMap.put("displayName", "liaowufeng");              // 顯示名稱
            attMap.put("userPrincipalName", "lwf2_name@securitytest.boco"); // UPN 登入名
            attMap.put("sAMAccountName", "lwf2_name");            // 下層相容登入名

            // 3. 密碼與帳號控制位元
            String newPassword = "bA123456";
            attMap.put("unicodePwd", encodePassword(newPassword)); // AD 專用:UTF-16LE 編碼加雙引號

            int UF_NORMAL_ACCOUNT = 0x0200;
            int UF_DONT_EXPIRE_PASSWD = 0x10000; // 密碼永不過期
            // 啟用帳號:NORMAL_ACCOUNT | DONT_EXPIRE_PASSWD
            attMap.put("userAccountControl", Integer.toString(UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD));

            // 4. 執行建立
            String userDN = "CN=lwf2_count,CN=Users,DC=securitytest,DC=boco";
            LdapOperUtils.addContext(dirContext, userDN, attMap);
            System.out.println("User created and enabled successfully!");

        } finally {
            LdapConnectionFactory.closeDirContext(dirContext);
        }
    }

    /** AD unicodePwd 格式:UTF-16LE 編碼的 "password" 字串(含雙引號) */
    private static byte[] encodePassword(String pwd) throws UnsupportedEncodingException {
        String quoted = "\"" + pwd + "\"";
        return quoted.getBytes("UTF-16LE");
    }
}

關鍵技術點深度解析

1. objectClass 繼承鏈

AD 使用者必須包含 top → person → organizationalPerson → user 完整鏈,缺一不可。

2. 密碼屬性:unicodePwd vs userPassword

  • userPassword:標準 LDAP 屬性,多為明文或雜湊,AD 不支援直接寫入。
  • unicodePwd:AD 專屬,必須為 UTF-16LE 編碼的帶雙引號字串(如 "bA123456"),且僅限 SSL 連線寫入(安全需求)。測試代碼為簡化示範使用明文連線,生產環境務必啟用 SSL。

3. userAccountControl 位元組合

常數十六進位含義
UF_ACCOUNTDISABLE0x0002帳號停用
UF_PASSWD_NOTREQD0x0020無需密碼
UF_PASSWD_CANT_CHANGE0x0040使用者不可變更密碼
UF_NORMAL_ACCOUNT0x0200一般使用者帳號(啟用基礎旗標)
UF_DONT_EXPIRE_PASSWD0x10000密碼永不過期
UF_PASSWORD_EXPIRED0x800000密碼已過期

啟用帳號最小組合:UF_NORMAL_ACCOUNT (0x0200)。本範例加上 UF_DONT_EXPIRE_PASSWD 避免密碼過期強制變更。

4. DN 建構規則

CN=lwf2_count,CN=Users,DC=securitytest,DC=boco 中:

  • CN:Common Name(相對辨識名)
  • CN=Users:預設使用者容器(非 OU)
  • DC:網域元件

工具套件總結與擴充建議

五篇文章完整實作了:

  1. Env:連線參數封裝
  2. LdapConnectionFactory:連線池/直連管理、SSL、關閉重試
  3. LdapOperUtils:Context 增刪改名、屬性增刪改查、搜尋(單層/子樹/屬性投影)、群組成員維護、認證整合

可擴充方向:

  • 分頁搜尋(PagedResultsControl)支援大量資料
  • 異步異動通知(DirContext.addNamingListener)
  • Schema 查詢與驗證
  • Spring LDAP 整合適配器
  • 單元測試覆蓋率提升(Mock DirContext)

歡迎同好交流改進,共建更好用的 LDAP Java 工具箱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved