JNDI与LDAP

来源:互联网 发布:tengine windows安装 编辑:程序博客网 时间:2024/05/22 07:03

读使用JNDI访问Domino目录之后

  • 创建一个JNDI可用连接的过程
    • 创建一个HashTable,存入LDAP工厂类(Context.INITIAL_CONTEXT_FACTORY)、服务器地址(Context.PROVIDER_URL)、(如果需要验证的话)验证方式(Context.SECURITY_AUTHENTICATION)、用户账号(Context.SECURITY_PRINCEPAL)、用户证书(Context.SECURITY_CREDENTIALS)
    • 创建一个context对象(DirContext ctx = new InitialDirContext(env))
    • 调用该Context对象的查询、插入、删除等操作的方法

读JNDI访问LDAP目录服务之后

  • JNDI所有异常都继承于NamingException
  • 认证失败抛出AuthenticationException
  • DirContext.lookup(“cn=…,ou=…”)可以获取单个对象,通过cast可以实现对对象的转换
  • 列举上下文的方法DirContext.list(“ou=…”)和DirContext.listBindings(“ou=…”)

    • DirContext.list(“ou=…”)枚举所有NameClassPair(对象名:对象类型名)
    NamingEnumeration list = ctx.list("ou=...");while(list.hasMore()){NameClassPair nc = (NameClassPair)list.next();System.out.println(nc);}
    • DirContext.listBindings(“ou=…”)不仅枚举NameClassPair还包括了对象(对象名:对象类型名@对象)
    NamingEnumeration bindings = ctx.listBindings("ou=...");while(bindings.hasMore()){Binding bd = (Binding)bindings.next();System.out.println(bd.getName() + ":" + bd.getObject());}
  • namingEnumeration的终止通过三种形式,一般、显式、非显式
    • 正常的调用namingEnumeration,当hasMore正常的返回false时,NamingEnumeration终止
    • 在枚举过程中使用close()强行终止
    • 在枚举过程中抛出异常终止
  • 对对象进行绑定通过bind()方法实现

    Fruit fruit = new Fruit("orange");ctx.bind("cn=Favorite Fruit", fruit);

    通过上述例子能够把Fruit对象绑定到Favorite Fruit的对象名中,假如当前对象名已经绑定则会抛出NameAlreadyBoundException,应当用rebind()方法对上一对象解绑并重新绑定新的对象

  • 通过unbind()可以解除对一个对象的绑定

    ctx.unbind("cn=Favorite Fruit")
  • 重命名rename()

    ctx.rename("cn=old name", "cn=new name")
  • 创建ctx的子上下文

    Attributes atts = new BasicAttributes(true);//忽略大小写Attribute objclass = new BasicAttribute("objectclass");objclass.add("top");objclass.add("organizationalUnit");attrs.put(objclass);Context subctx = ctx.createSubcontext("NewOu", attrs);//创建ou=NewOu的上下文
  • 销毁上下文,ctx.destorySubcontext(“NewOu”)
  • 读取属性

    Attributes answer = ctx.getAttributes("cn...,ou=...");//获取某个对象的Attrs对象for(NamingEnumeration ae = answer.getAll();ae.hasMore();){Attribute attr = (Attribute)ae.next();System.out.println("attribute:" + attr.getID());for(NamingEnumeration e = attr.getAll();attr.hasMore();){    System.out.println("value:" + e.next());}}
  • 返回选中的属性,通过数组指定返回什么属性

    String[] attrIDs = {"an", "telephonenumber"};Attributes answer = ctx.getAttributes("cn=...,ou=...", attrIDs);
  • 修改列表的方式之一是通过ModificationItem对象实现的,它定义了三种修改方法

    • ADD_ATTRIBUTE
    • REPLACE_ATTIRBUTE
    • REMOVE_ATTRIBUTE
    ModificationItem[] mods = new ModificationItem[3];mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("mail", "979831398@qq.com"));mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("telephonenumber", "5555555"));mods[2] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("jpegphoto"))ctx.modifyAttributes(name, mods);

    ps:在为telephone中增加新值时要注意telephonenumber的约束,是否允许存在多值,这些约束应该被定义在scheme文件中。


  • DirContext.bind()可以添加有属性的绑定,通过ctx.bind(“ou=favorite,ou=Fruits”, fruit, attrs)
  • 同样的,通过rebind可以替换有属性的绑定
  • JNDI对搜索的支持提供了三种搜索方式,分别是基本搜索、搜索过滤器、搜索控制

    • 基本搜索

      Attributes matchAttrs = new BasicAttributes(true);matchAttrs.put(new BasicAttribute("sn", "GGG"));//指定必须含有sn属性,其值必须是GGGmatchAttrs.put(new BasicAttribute("mail"));//指定必须含有mail属性,其值任意NamingEnumeration answer = ctx.search("ou=People", matchAttrs);//指定在ou=People中查询数据返回基本搜索中选中的属性同样可以通过attriIDs指定String[] attrIDs = {"sn", "telephonenumber", "sex"}NamingEnumeration answer = ctx.search("ou=People", matchAttrs, attrIDs);
    • 搜索过滤器
      搜索过滤器支持搜索语法,它同样适用search方法,但是它要求指定一个搜索控制器和对应的搜索字符串

    SearchControls ctls = new SearchControls()String filter = "(&(sn=GGG)(mail=*))";//改过滤器与上文等价NamingEnumeration answer = ctx.search("ou=People", filter, ctls);
    • 搜索过滤器语法
    & 仅当条目对于&所在域内所有项为true时获取该条目| 当条目对于|所在区域内任意项为true时获取该条目! 对条件求反= 指定属性值必须为某一确定值时~= 近似等于>= 大于<= 小于=* 存在某属性时返回条目* 通配符,如L*匹配LP、LD等\ 转义字符

    搜索过滤器用括号区分所在区域

  • 返回选中属性同样通过attrIDs指定,不过它被设置在搜索过滤器中
String[] attrIDs = {"sn", "telephonenumber"};SearchControls ctls = new SearchControls();ctls.setReturningAttributes(attrIDs);
  • 通过SearchControls.setSearchScope()指定SearchControls的范围
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);//指定整棵子树范围NamingEnumeration answer = ctx.search("", filter, ctls);

也可以搜索命名对象,通过指定scope为SearchControls.OBJECT_SCOPE


  • 可以限制返回的结果集数量,通过SearchControls.setCountLimit(num);
  • 可以限制应答时间,通过SearchControls.setTimeLimit(n ms)指定应答时间,当应答时间结束,结束搜索。
  • 异常处理

LDAP服务器向其他工具应答(例如管理控制台)但不应答您程序的请求。
原因:服务器没有应答LDAP v3的连接全逆光球。一些服务器(尤其是公共服务器)不能正确的应答LDAP v3,使用忽略的方式代替拒绝。同时,一些LDAP v3服务器有错误处理机制,Sun的LDAP服务提供者自动发送并且通常返回特定服务器错误码。
解决方案:尝试设置环境参数“java.naming.ldap.version”为“2”。LDAP服务提供者默认尝试使用LDAP v3连接LDAP服务器,然后使用LDAP v2。如果服务器静默忽略v3的请求,那么提供者假设请求生效了。使用这种服务器,您必须显式的设置协议版本,确保服务器有正确的行为。
如果服务器是v3服务器,那么尝试在创建初始化上下文之前设置这些环境参数:env.put(Context.REFERRAL, “throw”);
这样关闭了LDAP提供者自动发送的控制

0 0