java ldap

LDAP 是轻量 目录访问协议,英文全称是 Lightweight Directory Access Protocol,一般都简称为 LDAP。LDAP 基于 X.500 标准的,但简单了许多并且可以根据需要进行定制。与 X.500 不同,LDAP 支持 TCP/IP。LDAP 的核心规范在 RFC 中都有定义,所有与 LDAP 相关的RFC 都可以在 LDAPman RFC 网页中找到。

目录结构

  • LDAP 目录以树状的层次结构来存储数据。
  • 象 DNS 的 主机名,LDAP 目录记录的标识名(Distinguished Name,简称 DN)用来读取单个记录,以及回溯到树的顶部。
  • LDAP 目录树的最顶部就是根,也就是所谓的 " 基准DN "。
  • 基准 DN 通常使用三种格式之一
    • 以 X.500 格式表示的基准 DN,例如 o=xxxx, c=CN
    • 用公司的 Internet 地址表示的基准 DN,例如 o=xxxx.com
    • 用 DNS 域名的不同部分组成的基准 DN,例如 dc=xxxx, dc=com
    • 如果使用活动目录(Active Directory),Microsoft 限制必须使用 DNS 域名格式。

组织数据

  • 在根目录下,数据从逻辑上区分开。
  • 大多数 LDAP 目录用 OU 从逻辑上把数据分开来。OU 表示
    Organization Unit ,在 X.500 协议中用来表示公司内部机构:销售部、财务部等等。
  • 现在 LDAP 还保留 ou= 这样的命名规则,但是扩展了分类的范围,可以分类为:ou=people, ou=groups, ou=devices 等等。
  • 更低一级的 OU 有时用来做更细的归类。

单独记录

  • DN 是 LDAP 记录项的名字。
  • 在 LDAP 目录中的所有记录项都有一个唯一的 Distinguished Name,也就是 DN。
  • 每一个 LDAP 记录项的 DN 是由两个部分组成的
    • 相对DN(RDN)
    • 记录在 LDAP 目录中的位置。
  • RDN 是 DN 中与目录树的结构无关的部分。
  • 在 LDAP 目录中存储的记录项都要有一个名字,通常存在 cn(Common Name)属性里。
  • 在 LDAP 中存储的对象都用 cn 值作为 RDN 的基础。
  • 为公司的员工设置一个 DN

基于登录名(uid (User ID)与 unix 的 uid 完全不同)

uid=abc123, ou=xxxx, dc=xxxx, dc=com

基于姓名(cn)

cn=abc, ou=xxxx, dc=xxxx, dc=com
  • 这种格式有明显的缺点,名字发生改变,LDAP 的记录就要从一个 DN 转移到另一个 DN。

定制对象

  • LDAP 目录可以定制成存储任何文本或二进制数据。
  • LDAP 目录用对象类型(object classes)的概念来定义运行哪一类的对象使用什么属性。
  • LDAP 目录以一系列 " 属性对 " 的形式来存储记录项,每一个记录项包括属性类型和属性值(这与关系型数据库用行和列来存取数据有根本的不同)。
  • LDAP 目录被设计成为一个属性保存多个值的,而不是在每一个属性的后面用逗号把一系列值分开。这样的方式存储数据,数据库有很大的灵活性,不必为加入一些新的数据就重新创建表和索引。
  • LDAP 目录不必花费内存或硬盘空间处理 " 空 " 域,也就是说,实际上不使用可选择的域也不会花费任何资源。
  • 记录项的格式是 LDIF,用来导入和导出 LDAP 目录的记录项。
  • 属性的值在保存的时候是保留大小写的,但是在默认情况下搜索的时候是不区分大小写的。
  • 某些特殊的属性(例如,password)在搜索的时候需要区分大小写。
属性名称 含义 备注
OU Organizational Unit(组织单元) 最多可以有四级,每级最长 32 个字符,可以为中文。
DC Domain Component(域名) dc=xxxx,dc=com
CN Common Name(用户名或服务器名) 最长可以到 80 个字符,可以为中文。
O Organization(组织名称) 可以 3~64 个字符长度。
C Country(国家名) 可选,为 2 个字符长度。
SN  
UID 用户ID  
DN 唯一标识 类似于 Linux 文件系统的绝对路径,每个对象都有一个唯一的名称。

Java 中 LDAP 的基本操作

LDAP 连接

Hashtable env = new Hashtable();
String LDAP_URL = "ldap://<IP>:389"; // LDAP 访问地址
String adminName = "example\\user"; // 注意用户名的写法:domain\User 或 cn=user
String adminPassword = "userpassword"; // 密码
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, LDAP_URL);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, adminName);
env.put(Context.SECURITY_CREDENTIALS, adminPassword);
try {
     dc = new InitialDirContext(env);// 初始化上下文
     System.out.println("认证成功");
} catch (javax.naming.AuthenticationException e) {
     System.out.println("认证失败");
} catch (Exception e) {
     System.out.println("认证出错:" + e);
}

LDAP 增加记录

String root = "dc=example,dc=com"; // LDAP的根节点的DC

BasicAttributes attrs = new BasicAttributes();
BasicAttribute objclassSet = new BasicAttribute("objectClass");
objclassSet.add("sAMAccountName");
objclassSet.add("employeeID");
objclassSet.add("sAMAccountName");
objclassSet.add("employeeID");
attrs.put(objclassSet);
attrs.put("ou", newUserName);
dc.createSubcontext("ou=" + newUserName + "," + root, attrs);

LDAP 删除记录

try {
     dc.destroySubcontext(dn);
} catch (Exception e) {
     e.printStackTrace();
     System.out.println("Exception in delete():" + e);
}

LDAP 重命名节点

扫描二维码关注公众号,回复: 5907013 查看本文章
try {
      dc.rename(oldDN, newDN);
      return true;
} catch (NamingException ne) {
      System.err.println("Error: " + ne.getMessage());
      return false;
}

LDAP 修改

try {
      ModificationItem[] mods = new ModificationItem[1];
      /* 修改属性 */
      // Attribute attr0 = new BasicAttribute("employeeID", "test");
      // mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr0);
      /* 删除属性 */
      // Attribute attr0 = new BasicAttribute("description", "test");
      // mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, attr0);
      /* 添加属性 */
      Attribute attr0 = new BasicAttribute("employeeID", employeeID);
      mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr0);
      /* 修改 */
      dc.modifyAttributes(dn + ",dc=example,dc=com", mods);
      return true;
} catch (NamingException e) {
      e.printStackTrace();
      System.err.println("Error: " + e.getMessage());
      return false;
}

LDAP 查询

// 创建搜索控件
SearchControls searchCtls = new SearchControls();
// 设置搜索范围
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// 设置搜索过滤条件
String searchFilter = "sAMAccountName=" + userName;
// 设置搜索域节点
String searchBase = "DC=example,DC=COM";
// 定制返回属性
String returnedAtts[] = { "url", "whenChanged", "employeeID", "name", "userPrincipalName", "physicalDeliveryOfficeName", "departmentNumber", "telephoneNumber", "homePhone", "mobile", "department", "sAMAccountName", "whenChanged", "mail" };
// 不定制属性,返回所有的属性集
// searchCtls.setReturningAttributes(null);
int totalResults = 0;
try {
     NamingEnumeration answer = dc.search(searchBase, searchFilter, searchCtls);
     while (answer.hasMoreElements()) {
           SearchResult sr = (SearchResult) answer.next();
           Attributes Attrs = sr.getAttributes();
           if (Attrs != null) {
                 try {
                        for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore();) {
                                Attribute Attr = (Attribute) ne.next();
                                // 读取属性值
                                for (NamingEnumeration e = Attr.getAll(); e.hasMore(); totalResults++) {
                                         // 接受循环遍历读取的userPrincipalName用户属性
                                         String user = e.next().toString();
                                }
                                // 读取属性值
                                // Enumeration values = Attr.getAll();
                                // if (values != null) {
                                //          while (values.hasMoreElements()) {
                                //                   System.out.println(" 2AttributeValues=" + values.nextElement());
                                //          }
                                // }
                        }
                 } catch (NamingException e) {
                        System.err.println("Throw Exception : " + e);
                 }
           }
     }
} catch (Exception e) {
      e.printStackTrace();
      System.err.println("Throw Exception : " + e);
}
  • 搜索范围包含
    • 本节点:SearchControls.OBJECT_SCOPE
    • 单层:SearchControls.ONELEVEL_SCOPE
    • 遍历:SearchControls.SUBTREE_SCOPE

LDAP 关闭

if (dc != null) {
     try {
         dc.close();
     } catch (NamingException e) {
         System.out.println("NamingException in close():" + e);
     }
}


 

猜你喜欢

转载自blog.csdn.net/bobbykey/article/details/88966040