2023年6月21日发(作者:)

轻量级⽬录访问协议(LDAP)的整理 LDAP的英⽂全称是Lightweight Directory Access Protocol,即轻量级⽬录访问协议.我们知道,⼈们对计算机⽹络的使⽤和管理涉及了各种庞杂的资源,信息.为了提⾼性能,便于使⽤,有效管理分布式应⽤的服务,资源,⽤户及别的对象信息,这些信息需要清晰,⼀致地组织起来.基于这样的需求,描述各种⽤户,应⽤,⽂件,打印机和其它可从⽹络访问的资源的信息被集中到⼀个特殊的数据库中,这种数据库被称为⽬录.⽬录存放对象的公开或⾮公开的信息,这些信息以某种顺序组织,描述了每个对象的细节.电话簿,图书馆藏书卡⽚⽬录就是常见的⽬录. LDAP是基于X.500标准的,访问 X.500 ⽬录需要某种协议,例如:⽬录访问协议 (DAP).然⽽,DAP 需要⼤量的系统资源和⽀持机制来处理复杂的协议.LDAP 仅通过使⽤原始 X.500⽬录存取协议 (DAP) 的功能⼦集⽽减少了所需的系统资源消耗,⽽且可以根据需要定制.此外,与X.500不同,LDAP⽀持TCP/IP,这对访问Internet是必须的. 为了能对LDAP协议进⾏更好的理解,我们需要对以下概念有初步的认识:⽬录:Directory,存放对象的信息,这些信息以某种顺序组织,详细描述每个对象.⽬录信息树:DIT,Directory Information Tree,⽬录条⽬的集合构成了⽬录信息树.条⽬:Entry,⽬录信息树中的⼀个结点,是⼀个对象信息的集合,是⽬录信息中最基本的单位,包含该对象的⼀系列属性.属性:Attribute,属性描述对象的特征.⼀个属性由属性类型(type)和⼀个或多个属性值(values)构成.相对标识名:RDN,Relative Distinguished Name,条⽬的名字.唯⼀标识名:DN,Distinguished Name,在⼀个⽬录信息树中唯⼀标识⼀个条⽬的名字. LDAP(轻量级⽬录访问协议,Lightweight Directory Access Protocol)是实现提供被称为⽬录服务的信息服务。

⽬录服务是⼀种特殊的数据库系统,其专门针对读取,浏览和搜索操作进⾏了特定的优化。⽬录⼀般⽤来包含描

述性的,基于属性的信息并⽀持精细复杂的过滤能⼒。⽬录⼀般不⽀持通⽤数据库针对⼤量更新操作操作需要的

复杂的事务管理或回卷策略。⽽⽬录服务的更新则⼀般都⾮常简单。这种⽬录可以存储包括个⼈信息、web链结、

jpeg图像等各种信息。为了访问存储在⽬录中的信息,就需要使⽤运⾏在TCP/IP之上的访问协议—LDAP。 LDAP⽬录中的信息是是按照树型结构组织,具体信息存储在条⽬(entry)的数据结构中。条⽬相当于关系数据库中

表的记录;条⽬是具有区别名DN(Distinguished Name)的属性(Attribute),DN是⽤来引⽤条⽬的,DN相当于

关系数据库表中的关键字(Primary Key)。属性由类型(Type)和⼀个或多个值(Values)组成,相当于关系数

据库中的字段(Field)由字段名和数据类型组成,只是为了⽅便检索的需要,LDAP中的Type可以有多个Value,

⽽不是关系数据库中为降低数据的冗余性要求实现的各个域必须是不相关的。LDAP中条⽬的组织⼀般按照地理位置和组织关系进⾏组织,⾮常的直观。LDAP把数据存放在⽂件中,为提⾼效率可以使⽤基于索引的⽂件数据库,⽽不是关系数据库。类型的⼀个例⼦就是mail,其值将是⼀个电⼦邮件地址。WebLogic的内置的LDAP Server⽀持IETF LDAP为LDAPv3制定的控制访问模型。下⾯这个⽚断将讲述在内置的LDAP

Server中怎样实现控制访问。可以通过编辑访问控制⽂件来将这些规则直接应⽤到⽬录的⼊⼝。WebLogic中的访问控制⽂件是。在Server的lib中可以找到这个⽂件。这个⽂件的所有访问控制规则都被注释掉了,如果想更改这些规则,你要⼿⼯更改这个⽂件。注意:WebLogic Server内置的LDAP Server在默认的情况下只允许Admin帐号访问,WebLogic Server的security providers只使⽤Admin帐号访问内置的LDAP Server。如果你不想使⽤外部的LDAP Brower访问WebLogic Server的内置的LDAP Server,或者你只想使⽤Admin帐号访问内置的LDAP Server,你不需要编辑⽂件,访问控制⽂件(The Access Control File)访问控制⽂件()包含内置的LDAP Server的整个⽬录的完整的访问控制列表(ACL)。这个⽂件中的每⼀⾏都包含⼀个访问控制规则。⼀个访问控制规则由下⾯接个部分组成: 访问控制位置(Access Control Location) 每个访问控制规则都应⽤于LDAP⽬录中的⼀个给定的位置。这个位置通常是⼀个区别命名(DN),但有⼀个例外,这就是[root],如果访问控制规则应⽤到整个⽬录,则只需要指定位置为[root]就可以了! 如果被访问或更改的⼊⼝的位置与访问控制规则指定的位置不相等,或在访问控制规则指定的位置的下级,则这个访问控制规则将不会被执⾏。 访问控制范围(Access Control Scope) 访问控制范围有2种: Entry-⼀个Entry范围的访问控制列表只在下⾯的情况下被执⾏: LDAP⽬录的⼊⼝的DN与访问控制规则指定的位置相同。这样的规则对于包含了⽐并⾏和副⼊⼝更敏感信息的单独⼊⼝⾮常有⽤。 Subtree-意味着访问控制规则指定的位置及⼦树都可以适⽤这条规则。 如果Entry与Subtree在访问控制规则中有冲突,则Entry要优先于Subtree。 访问权限(Access Rights) 访问权限应⽤于整个对象或对象的属性,有2个值:grant(准许)或deny(拒绝)。访问权限指定了LDAP操作的类型。

许可(grant或deny) 应⽤规则的属性(attribute) 允许或拒绝访问的主题(subject) 在weblogic可以编写程序来访问LDAP.上⼿时可以选择JXplorer⼯具。 Server及LDAP Browser: 对于WLS LDAP为理解起来简单,去掉限制的⽅法是修改bea/weblogic81/server/lib/⽂件后。修改⽅法:在该⽂件最后添加以下⼏⾏。[root]|entry#grant:s,r,o,w,c,m#[all]#public[root]|subtree#grant:s,r,o,w,c,m#[all]#public:[root]|subtree#grant:a,d,e,i,n,b,t#[entry]#public:cn=schema|entry#grant:s,r,o,w,c,m#[all]#public:cn=schema|entry#grant:a,d,e,i,n,b,t#[entry]#public:注意,该⽂件中这些⾏之间,以及其他⾏之间不能有空⾏,否则启动WLS会报错的。修改好之后就可以启动WLS了,启动后进⼊Console⾥修改Ldap Server的密码。密码修改完后需要再重新启动⼀次WLS。LDAP刚上⼿的时候没有⽅便的⼯具会很费劲。我看了CSDN上“兔⼋哥”的⽂章,⽤JXplorer,感觉很不错。想看这篇⽂章,到CSDN上搜⼀下“兔⼋哥”,系列中No.12就是关于JXplorer的配置和使⽤。我的连接参数如下:Host:localhost//根据实际修改Port:7001Protocol:LDAP v3Base DN:dc=ldapdomain//根据实际修改Level:User+PasswordUser DN:cn=AdminPassword:weblogic//根据实际修改.编程操作LDAP Server。 下⾯四个JAVA⽅法,分别⽤于初始化,查询,添加,删除,修改,关闭连接。 记得每次都需要先⼤概连接,操作,然后关闭连接。和使⽤数据库差不多。

⾸先是需要⽤到的头⽂件:import ble;import ation;import t;import Exception;import text;import lDirContext;import Controls ;import Enumeration;import Result;import utes ;import ute;import ttributes;import ttribute;import cationItem;import ;import edReader;import treamReader; 然后是⼀个类域,⽤于保存上下⽂:

DirContext ctx = null;

然后是初始化:

public void init(){ String account="Admin";//操作LDAP的帐户。默认就是Admin。 String password="weblogic";//帐户Admin的密码。 String root="dc=ldapdomain"; //所操作的WLS域。也就是LDAP的根节点的DC Hashtable env = new Hashtable(); (L_CONTEXT_FACTORY, "xFactory");//必须这样写,⽆论⽤什么LDAP服务器。 (ER_URL, "" + root);//LDAP服务器的地址:端⼝。对WLS端⼝就是7001 (TY_AUTHENTICATION, "none");//授权界别,可以有三种授权级别,但是如果设为另外两种都⽆法登录,我也不知道为啥,但是只能设成这个值"none"。 (TY_PRINCIPAL, "cn=" + account + "," + root);//载⼊登陆帐户和登录密码 (TY_CREDENTIALS, password); try{ ctx = new InitialDirContext(env);//初始化上下⽂ n("认证成功");//这⾥可以改成异常抛出。 }catch(ticationException e){ n("认证失败"); }catch(Exception e){ n("认证出错:"+e); } }

查询操作:

public void search(){//我只能按照某些属性查找节点,偶还不会怎么查找⼀个⽬录或按照更复杂的正则式查找特定节点/⽬录 try{ SearchControls constraints = new SearchControls(); rchScope(E_SCOPE); ("what would you want to search:"); BufferedReader bd=new BufferedReader(new InputStreamReader()); String s=ne(); NamingEnumeration en = ("", "uid="+s, constraints); //要查询的UID。如果是*则可以查到所有UID的节点 if(en == null){ n("Have no NamingEnumeration."); } if(!eElements()){ n("Have no element."); } while (en != null && eElements()){//可以查出多个元素 Object obj = ement(); if(obj instanceof SearchResult){ SearchResult si = (SearchResult) obj; n("/tname: " + e()); Attributes attrs = ributes(); if (attrs == null){ n("/tNo attributes"); }else{ for (NamingEnumeration ae = (); eElements();){//获得该节点的所有属性 Attribute attr = (Attribute) ();//下⼀属性 Attribute attr = (Attribute) ();//下⼀属性 String attrId = ();//获得该属性的属性名 for (Enumeration vals = ();eElements();){//获得⼀个属性中的所有属性值 ("/t/t"+attrId + ": "); Object o = ement();//下⼀属性值 if(o instanceof byte[]) n(new String((byte[])o)); else n(o); } } } } else{ n(obj); } n(); } }catch(Exception e){ n("Exception in search():"+e); } }

添加操作:

public void add(){ try{ String newUserName = "stella"; BasicAttributes attrs = new BasicAttributes(); BasicAttribute objclassSet = new BasicAttribute("objectclass"); ("person");

("top");

("organizationalPerson");

("inetOrgPerson"); ("wlsUser"); (objclassSet); ("sn", newUserName); ("uid", newUserName); ("cn", newUserName); Subcontext("uid=" + newUserName+",ou=people,ou=myrealm", attrs); //添加⼀个节点,我还不会添加⽬录 }catch(Exception e){ n("Exception in add():"+e); } } 修改操作:

public void edit(){ try{ String account = "stella";//修改以前旧的值 String sn = "stella sn";//修改以后新的值 ModificationItem modificationItem[] = new ModificationItem[1]; modificationItem[0] = new ModificationItem( E_ATTRIBUTE, new BasicAttribute("sn", sn));//所修改的属性 Attributes("uid=" + account, modificationItem); //执⾏修改操作 }catch(Exception e){ n("Exception in edit():"+e); } }

删除节点操作:

public void delete(){ try{ String uid = "stella"; ySubcontext("uid=" + uid); //按照UID删除某个节点。我还不会删除⼀个⽬录。 }catch(Exception e){ n("Exception in edit():"+e); } }

关闭连接:

public void close(){ if(ctx != null) { try { (); } catch (NamingException e) { n("NamingException in close():"+e); } }

}我对LDAP的理解:它是⽤于对资源的管理和服务的访问协议,在Weblogic平台上的JNDI(包含EJB和DataSource)都是提供它来提供的。正是JNDI的服务和RMI结合就形成J2EE平台上分布式的应⽤,因此说到底层,还是LDAP协议的⽀持。

2023年6月21日发(作者:)

轻量级⽬录访问协议(LDAP)的整理 LDAP的英⽂全称是Lightweight Directory Access Protocol,即轻量级⽬录访问协议.我们知道,⼈们对计算机⽹络的使⽤和管理涉及了各种庞杂的资源,信息.为了提⾼性能,便于使⽤,有效管理分布式应⽤的服务,资源,⽤户及别的对象信息,这些信息需要清晰,⼀致地组织起来.基于这样的需求,描述各种⽤户,应⽤,⽂件,打印机和其它可从⽹络访问的资源的信息被集中到⼀个特殊的数据库中,这种数据库被称为⽬录.⽬录存放对象的公开或⾮公开的信息,这些信息以某种顺序组织,描述了每个对象的细节.电话簿,图书馆藏书卡⽚⽬录就是常见的⽬录. LDAP是基于X.500标准的,访问 X.500 ⽬录需要某种协议,例如:⽬录访问协议 (DAP).然⽽,DAP 需要⼤量的系统资源和⽀持机制来处理复杂的协议.LDAP 仅通过使⽤原始 X.500⽬录存取协议 (DAP) 的功能⼦集⽽减少了所需的系统资源消耗,⽽且可以根据需要定制.此外,与X.500不同,LDAP⽀持TCP/IP,这对访问Internet是必须的. 为了能对LDAP协议进⾏更好的理解,我们需要对以下概念有初步的认识:⽬录:Directory,存放对象的信息,这些信息以某种顺序组织,详细描述每个对象.⽬录信息树:DIT,Directory Information Tree,⽬录条⽬的集合构成了⽬录信息树.条⽬:Entry,⽬录信息树中的⼀个结点,是⼀个对象信息的集合,是⽬录信息中最基本的单位,包含该对象的⼀系列属性.属性:Attribute,属性描述对象的特征.⼀个属性由属性类型(type)和⼀个或多个属性值(values)构成.相对标识名:RDN,Relative Distinguished Name,条⽬的名字.唯⼀标识名:DN,Distinguished Name,在⼀个⽬录信息树中唯⼀标识⼀个条⽬的名字. LDAP(轻量级⽬录访问协议,Lightweight Directory Access Protocol)是实现提供被称为⽬录服务的信息服务。

⽬录服务是⼀种特殊的数据库系统,其专门针对读取,浏览和搜索操作进⾏了特定的优化。⽬录⼀般⽤来包含描

述性的,基于属性的信息并⽀持精细复杂的过滤能⼒。⽬录⼀般不⽀持通⽤数据库针对⼤量更新操作操作需要的

复杂的事务管理或回卷策略。⽽⽬录服务的更新则⼀般都⾮常简单。这种⽬录可以存储包括个⼈信息、web链结、

jpeg图像等各种信息。为了访问存储在⽬录中的信息,就需要使⽤运⾏在TCP/IP之上的访问协议—LDAP。 LDAP⽬录中的信息是是按照树型结构组织,具体信息存储在条⽬(entry)的数据结构中。条⽬相当于关系数据库中

表的记录;条⽬是具有区别名DN(Distinguished Name)的属性(Attribute),DN是⽤来引⽤条⽬的,DN相当于

关系数据库表中的关键字(Primary Key)。属性由类型(Type)和⼀个或多个值(Values)组成,相当于关系数

据库中的字段(Field)由字段名和数据类型组成,只是为了⽅便检索的需要,LDAP中的Type可以有多个Value,

⽽不是关系数据库中为降低数据的冗余性要求实现的各个域必须是不相关的。LDAP中条⽬的组织⼀般按照地理位置和组织关系进⾏组织,⾮常的直观。LDAP把数据存放在⽂件中,为提⾼效率可以使⽤基于索引的⽂件数据库,⽽不是关系数据库。类型的⼀个例⼦就是mail,其值将是⼀个电⼦邮件地址。WebLogic的内置的LDAP Server⽀持IETF LDAP为LDAPv3制定的控制访问模型。下⾯这个⽚断将讲述在内置的LDAP

Server中怎样实现控制访问。可以通过编辑访问控制⽂件来将这些规则直接应⽤到⽬录的⼊⼝。WebLogic中的访问控制⽂件是。在Server的lib中可以找到这个⽂件。这个⽂件的所有访问控制规则都被注释掉了,如果想更改这些规则,你要⼿⼯更改这个⽂件。注意:WebLogic Server内置的LDAP Server在默认的情况下只允许Admin帐号访问,WebLogic Server的security providers只使⽤Admin帐号访问内置的LDAP Server。如果你不想使⽤外部的LDAP Brower访问WebLogic Server的内置的LDAP Server,或者你只想使⽤Admin帐号访问内置的LDAP Server,你不需要编辑⽂件,访问控制⽂件(The Access Control File)访问控制⽂件()包含内置的LDAP Server的整个⽬录的完整的访问控制列表(ACL)。这个⽂件中的每⼀⾏都包含⼀个访问控制规则。⼀个访问控制规则由下⾯接个部分组成: 访问控制位置(Access Control Location) 每个访问控制规则都应⽤于LDAP⽬录中的⼀个给定的位置。这个位置通常是⼀个区别命名(DN),但有⼀个例外,这就是[root],如果访问控制规则应⽤到整个⽬录,则只需要指定位置为[root]就可以了! 如果被访问或更改的⼊⼝的位置与访问控制规则指定的位置不相等,或在访问控制规则指定的位置的下级,则这个访问控制规则将不会被执⾏。 访问控制范围(Access Control Scope) 访问控制范围有2种: Entry-⼀个Entry范围的访问控制列表只在下⾯的情况下被执⾏: LDAP⽬录的⼊⼝的DN与访问控制规则指定的位置相同。这样的规则对于包含了⽐并⾏和副⼊⼝更敏感信息的单独⼊⼝⾮常有⽤。 Subtree-意味着访问控制规则指定的位置及⼦树都可以适⽤这条规则。 如果Entry与Subtree在访问控制规则中有冲突,则Entry要优先于Subtree。 访问权限(Access Rights) 访问权限应⽤于整个对象或对象的属性,有2个值:grant(准许)或deny(拒绝)。访问权限指定了LDAP操作的类型。

许可(grant或deny) 应⽤规则的属性(attribute) 允许或拒绝访问的主题(subject) 在weblogic可以编写程序来访问LDAP.上⼿时可以选择JXplorer⼯具。 Server及LDAP Browser: 对于WLS LDAP为理解起来简单,去掉限制的⽅法是修改bea/weblogic81/server/lib/⽂件后。修改⽅法:在该⽂件最后添加以下⼏⾏。[root]|entry#grant:s,r,o,w,c,m#[all]#public[root]|subtree#grant:s,r,o,w,c,m#[all]#public:[root]|subtree#grant:a,d,e,i,n,b,t#[entry]#public:cn=schema|entry#grant:s,r,o,w,c,m#[all]#public:cn=schema|entry#grant:a,d,e,i,n,b,t#[entry]#public:注意,该⽂件中这些⾏之间,以及其他⾏之间不能有空⾏,否则启动WLS会报错的。修改好之后就可以启动WLS了,启动后进⼊Console⾥修改Ldap Server的密码。密码修改完后需要再重新启动⼀次WLS。LDAP刚上⼿的时候没有⽅便的⼯具会很费劲。我看了CSDN上“兔⼋哥”的⽂章,⽤JXplorer,感觉很不错。想看这篇⽂章,到CSDN上搜⼀下“兔⼋哥”,系列中No.12就是关于JXplorer的配置和使⽤。我的连接参数如下:Host:localhost//根据实际修改Port:7001Protocol:LDAP v3Base DN:dc=ldapdomain//根据实际修改Level:User+PasswordUser DN:cn=AdminPassword:weblogic//根据实际修改.编程操作LDAP Server。 下⾯四个JAVA⽅法,分别⽤于初始化,查询,添加,删除,修改,关闭连接。 记得每次都需要先⼤概连接,操作,然后关闭连接。和使⽤数据库差不多。

⾸先是需要⽤到的头⽂件:import ble;import ation;import t;import Exception;import text;import lDirContext;import Controls ;import Enumeration;import Result;import utes ;import ute;import ttributes;import ttribute;import cationItem;import ;import edReader;import treamReader; 然后是⼀个类域,⽤于保存上下⽂:

DirContext ctx = null;

然后是初始化:

public void init(){ String account="Admin";//操作LDAP的帐户。默认就是Admin。 String password="weblogic";//帐户Admin的密码。 String root="dc=ldapdomain"; //所操作的WLS域。也就是LDAP的根节点的DC Hashtable env = new Hashtable(); (L_CONTEXT_FACTORY, "xFactory");//必须这样写,⽆论⽤什么LDAP服务器。 (ER_URL, "" + root);//LDAP服务器的地址:端⼝。对WLS端⼝就是7001 (TY_AUTHENTICATION, "none");//授权界别,可以有三种授权级别,但是如果设为另外两种都⽆法登录,我也不知道为啥,但是只能设成这个值"none"。 (TY_PRINCIPAL, "cn=" + account + "," + root);//载⼊登陆帐户和登录密码 (TY_CREDENTIALS, password); try{ ctx = new InitialDirContext(env);//初始化上下⽂ n("认证成功");//这⾥可以改成异常抛出。 }catch(ticationException e){ n("认证失败"); }catch(Exception e){ n("认证出错:"+e); } }

查询操作:

public void search(){//我只能按照某些属性查找节点,偶还不会怎么查找⼀个⽬录或按照更复杂的正则式查找特定节点/⽬录 try{ SearchControls constraints = new SearchControls(); rchScope(E_SCOPE); ("what would you want to search:"); BufferedReader bd=new BufferedReader(new InputStreamReader()); String s=ne(); NamingEnumeration en = ("", "uid="+s, constraints); //要查询的UID。如果是*则可以查到所有UID的节点 if(en == null){ n("Have no NamingEnumeration."); } if(!eElements()){ n("Have no element."); } while (en != null && eElements()){//可以查出多个元素 Object obj = ement(); if(obj instanceof SearchResult){ SearchResult si = (SearchResult) obj; n("/tname: " + e()); Attributes attrs = ributes(); if (attrs == null){ n("/tNo attributes"); }else{ for (NamingEnumeration ae = (); eElements();){//获得该节点的所有属性 Attribute attr = (Attribute) ();//下⼀属性 Attribute attr = (Attribute) ();//下⼀属性 String attrId = ();//获得该属性的属性名 for (Enumeration vals = ();eElements();){//获得⼀个属性中的所有属性值 ("/t/t"+attrId + ": "); Object o = ement();//下⼀属性值 if(o instanceof byte[]) n(new String((byte[])o)); else n(o); } } } } else{ n(obj); } n(); } }catch(Exception e){ n("Exception in search():"+e); } }

添加操作:

public void add(){ try{ String newUserName = "stella"; BasicAttributes attrs = new BasicAttributes(); BasicAttribute objclassSet = new BasicAttribute("objectclass"); ("person");

("top");

("organizationalPerson");

("inetOrgPerson"); ("wlsUser"); (objclassSet); ("sn", newUserName); ("uid", newUserName); ("cn", newUserName); Subcontext("uid=" + newUserName+",ou=people,ou=myrealm", attrs); //添加⼀个节点,我还不会添加⽬录 }catch(Exception e){ n("Exception in add():"+e); } } 修改操作:

public void edit(){ try{ String account = "stella";//修改以前旧的值 String sn = "stella sn";//修改以后新的值 ModificationItem modificationItem[] = new ModificationItem[1]; modificationItem[0] = new ModificationItem( E_ATTRIBUTE, new BasicAttribute("sn", sn));//所修改的属性 Attributes("uid=" + account, modificationItem); //执⾏修改操作 }catch(Exception e){ n("Exception in edit():"+e); } }

删除节点操作:

public void delete(){ try{ String uid = "stella"; ySubcontext("uid=" + uid); //按照UID删除某个节点。我还不会删除⼀个⽬录。 }catch(Exception e){ n("Exception in edit():"+e); } }

关闭连接:

public void close(){ if(ctx != null) { try { (); } catch (NamingException e) { n("NamingException in close():"+e); } }

}我对LDAP的理解:它是⽤于对资源的管理和服务的访问协议,在Weblogic平台上的JNDI(包含EJB和DataSource)都是提供它来提供的。正是JNDI的服务和RMI结合就形成J2EE平台上分布式的应⽤,因此说到底层,还是LDAP协议的⽀持。