ldap的学习

一、ldap是什么?

Light Directory Access Protocol,轻量级目录访问协议.

dn (Distinguished Name):一条记录的位置
dc :一条记录所属区域
ou :一条记录所属组织
cn/uid:一条记录的名字/ID

LDAP中,schema用来指定一个目录中所包含的objects的类型(objectClass)以及每一个objectClass中的各个必备(mandatory)和可选(optional)的属性(attribute)。因此,Schema是一个数据模型,它被用来决定数据怎样被存储,被跟踪的数据的是什么类型,存储在不同的Entry下的数据之间的关系。schema需要在主配置文件slapd.conf中指定,以用来决定本目录中使用到的objectClass。管理员可以自己设计制定schema,一般包括属性定义(AttributeDefinition)、类定义(ClassDefinition)以及语法定义(SyntaxDefinition)等部分。 可以通过ldap的admin console来增加用户自定义的objectclass。
  

二、ldap的java代码(Sun Java(TM) System Directory Server 5.2)

ldap连接池的网址:http://java.sun.com/products/jndi/tutorial/ldap/connect/config.html

private static DirContext dc;

连接:

public static void connect(){
String dn="cn=Directory Manager"; //登陆用户

String password="";//dn的密码
String url="ldap://ip:389/"; //ldap server的host
String   root="dc=ahhexin,dc=com"; //basedn
Hashtable env = new Hashtable();
env.put(DirContext.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(DirContext.PROVIDER_URL, url); 
env.put(DirContext.SECURITY_AUTHENTICATION, "simple"); //Use simple authentication

if (dn != null) {
   env.put(DirContext.SECURITY_PRINCIPAL, dn);   
   env.put(DirContext.SECURITY_CREDENTIALS, password);
}
try {   
   dc = new InitialDirContext(env);
   System.out.println("认证成功");
     } catch (NamingException ex) {
     System.out.println("认证失败:" + ex.getMessage()+ex.getStackTrace());
   dc = null;
}      
}

在ldap认证时候,提示认证失败,查找原因方法:1、首先到到ldap server那台机器上用命令增加dn,具体是:

ldapadd -x -D "cn=Directory Manager" -w password,然后回车,如果没有报密码或者错误,说明此dn是可以登陆的。

2、检查网络,看看防火墙设置,在你的机器上运行:telnet ldapserver的ip ldap的端口,如果不通,就是网络问题或者机器配置问题。(我的ldap client跟ldap server不在一台机器上)。

ldap查询:

/**
* 查询条件:basedn,filter,searchControls
* 查询结果可能有more than one entry ,利用循环来取entry,每个entry存放结构是SearchResult中
* 每个entry有:dn和attributes
* 每个attributes有more than one attribute 
* 每个attribute有一个attriId,and more than one value
* 得到每个value值
*/
public static void selLdap(){
ArrayList listAll = new ArrayList(); 
String basedn="dc=ahhexin,dc=com";
String filter="objectClass=*";
SearchControls   cons = new SearchControls();

//查询有三个scope:OBJECT_SCOPE,ONELEVEL_SCOPE,SUBTREE_SCOPE
cons.setSearchScope(cons.SUBTREE_SCOPE); 
NamingEnumeration ne = null;
NamingEnumeration subne=null; 
try {
   ne=dc.search(basedn, filter, cons);
   while(ne.hasMore()){
    ArrayList ldapinfo =new ArrayList();
    SearchResult sr=(SearchResult)ne.next();
    String dn=sr.getName();
    System.out.println();
    System.out.println("dn: "+dn); //这个地方dn是rdn
    ldapinfo.add(dn);
    Attributes ats = sr.getAttributes();
    subne=ats.getAll();
    while(subne.hasMore()){
     Attribute at = (Attribute)subne.next();
     String attrId=at.getID();      
     NamingEnumeration valNe=at.getAll();
     while(valNe.hasMore()){
      Object attrVal = valNe.nextElement();
      System.out.println(attrId+": "+ attrVal);
      if(attrVal instanceof String)
       ldapinfo.add(attrId+": "+ attrVal);    
      else
       ldapinfo.add(attrId+": "+ new String((byte[])attrVal));              
     }
    }
    listAll.add(ldapinfo);
   }
} catch (NamingException e) {
   System.out.println("查询entries失败");
   e.printStackTrace();
}
}

ldap增加dn

/**
* 填写属性和dn,然后利用createSubcontext创建即可
*
*/ 
public static void addLdapEntry(){
String basedn="dc=ahhexin,dc=com";
String dn="uid=bjensen"+","+basedn;

BasicAttributes attrs =new BasicAttributes();
BasicAttribute objectclass = new BasicAttribute("objectClass");
objectclass.add("top");
objectclass.add("person");
objectclass.add("organizationalPerson");
objectclass.add("inetOrgPerson");
attrs.put(objectclass);
attrs.put("cn", "Barbara Jensen");
attrs.put("sn", "Jensen");
attrs.put("givenName", "Barbara");
attrs.put("title", "manager, product development");
attrs.put("uid", "bjensen");
attrs.put("mail", "zhangsan.com");
try {
   dc.createSubcontext(dn, attrs);
} catch (NamingException e) {
   System.out.println("增加entry失败");
   e.printStackTrace();

}

ldap修改dn的属性

/**
* 修改属性
*/
public static void modLdap(){
String basedn="dc=ahhexin,dc=com";
String dn="uid=bjensen"+","+basedn;
/**
   * 增加属性,如果增加的属性存在,则增加属性的值,如果此值已经存在,则报错
   */
BasicAttributes addattrs =new BasicAttributes();

addattrs.put("roomNumber", "0209"); 
addattrs.put("carLicense", "6ABC246");
try {
   dc.modifyAttributes(dn, DirContext.ADD_ATTRIBUTE, addattrs);
} catch (NamingException e1) {
   System.out.println("增加属性失败");
   e1.printStackTrace();
}
/**
   * 替换属性,替换属性如果不存在,就增加次属性
   */
BasicAttributes modattrs =new BasicAttributes();
BasicAttribute modattr = new BasicAttribute("mail");
modattr.add("[email protected]");
modattr.add("[email protected]");
modattrs.put(modattr);
modattrs.put("givenName", "Barbara1"); 
try {
   dc.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, modattrs);
} catch (NamingException e) {
   System.out.println("修改属性失败");
   e.printStackTrace();
}
/**
   * 删除属性,删除的属性需要存在,否则会报错
   */

BasicAttributes delattrs =new BasicAttributes();
delattrs.put("title", null); 
try {
   dc.modifyAttributes(dn, DirContext.REMOVE_ATTRIBUTE, delattrs);
} catch (NamingException e) {
   System.out.println("删除属性失败");
   e.printStackTrace();
}         
}

ldap修改dn的名称

/**
* 修改dn的名称,并且属性uid的值也改变了

* 如果dn是非叶子节点,是不允许修改的

* 修改rdn,不能修改dn中相对路径的值,比如A是ou=people1中的孩子,现在想A改成ou=people2中的孩子,此中情况不能直接修改dn,需要在ou=people1中删除A,然后到ou=people2中增加A
*
*/
public static void modifyLdapDn(){
String basedn="dc=ahhexin,dc=com";
String oldDn="uid=bjensen"+","+basedn;
String newDn="uid=bjensennew"+","+basedn;
try {
   dc.rename(oldDn, newDn);
} catch (NamingException e) {
   System.out.println("修改dn名称失败");
   e.printStackTrace();

}

ldap删除dn

/**
* 删除dn,如果dn下面还有node,此删除操作失败
*/
public static void delLdap(){ 
String basedn="dc=ahhexin,dc=com"; 
String dn="uid=bjensennew"+","+basedn;
try {
   dc.destroySubcontext(dn);
} catch (NamingException e) {
   System.out.println("删除entry失败");
   e.printStackTrace();
}
}

ldap关闭连接

public static void close()
{
if(dc!=null)
   try {
    dc.close();
   } catch (NamingException e) {
    System.out.println("关闭dc认证失败");
    e.printStackTrace();
   }
}

三、设计思考

LDAP中,一条记录必须包含一个objectClass属性,且其需要赋予至少一个值。每一个值将用作一条LDAP记录进行数据存储的模板;模板中包含了一条记录中数个必须被赋值的属性和一系列可选的属性。
    objectClass有着严格的等级之分,最顶层的类是top和alias。例如,organizationalPerson这个objectClass隶属于Person,而Person又是top的子类。

    objectClass大致分为三类:结构型的(如:person和organizationUnit)、辅助型的(如:extensibeObject)和抽象型的(这类不能直接使用)。官方定义的objectClass为http://ldap.akbkhome.com/index.php/objectclass.html

思考:ldap的objectclass的设计是inherit的,而我们在做ldap设计过程用的是关系型数据库bcd范式的设计思想,而ldap server中的数据存储方式跟关系型数据库存储方式不一样,我理解的ldap的存储方式是树型结构存储方式,所以ldap的查找是很高效的。

四、不错的ldap网址:http://blog.chinaunix.net/u/4206/showart_286820.html

http://www.ldapman.org/articles/tree_design.html

http://docs.sun.com/source/816-6852-10/intro.html

你可能感兴趣的:(ldap的学习)