完整功能示例 :DBMS_LDAP基础功能


参考:https://seanstuber.com/2018/08/01/how-to-use-dbms_ldap-part-1/ 

  1. 建立关闭连接

    下面示例是基本的匿名连接示例。

    DECLARE
        v_session   dbms_ldap.session;
        v_result    PLS_INTEGER;
    BEGIN
        --init 初始化连接session
        v_session := dbms_ldap.init(hostname => '180.76.186.73', portnum => dbms_ldap.port);
        
        if v_session is null then
            DBMS_OUTPUT.put_line('init failed');
        else
            --unbind 关闭session
            v_result := dbms_ldap.unbind_s(v_session);
            
            if v_result != DBMS_LDAP.success THEN
                DBMS_OUTPUT.put_line(TO_CHAR(v_result , 'fm9999') || ' ' || DBMS_LDAP.err2string(V_result));
            end if ;
        end if ;   
    
    END;


  2. 连接认证

    在LDAP中认证鉴权就是提供用户和密码,在LDAP的技术术语中称为binding。

    认证方法:
    1. SIMPLE_BIND_S
      使用固定的认证方式
      在LDAP中,用户密码的形式和普通不同,使用DN作为用户名。

      DECLARE
          v_session   DBMS_LDAP.session;
          v_result    PLS_INTEGER;
      BEGIN
          DBMS_LDAP.use_exception := TRUE;
          -- Establish a connection to LDAP server
          v_session := DBMS_LDAP.init(hostname => '180.76.186.73', 
                                      portnum => DBMS_LDAP.port);
      
      
          -- Login with the DN for a user account and password 
          v_result := DBMS_LDAP.simple_bind_s(
                            ld => v_session, 
                            dn => 'cn=admin,dc=dezohty,dc=com', 
                            passwd => 'adminpw');
      
          -- Even if you don't BIND a username/password, you should still UNBIND
          -- to close the session, there is no close
          v_result := DBMS_LDAP.unbind_s(v_session);
      END;
    2. BIND_S
      可选择认证方式
      Strangely,DBMS_LDAP defines multiple authentication constants but the documentation, as of 18c, claims: “The only valid value is DBMS_LDAP_UTL.AUTH_SIMPLE.”
    3. 使用SSL
  3. 搜索查询

    1. DECLARE
          v_result               PLS_INTEGER;
          v_session              DBMS_LDAP.session;
          v_search_attrs         DBMS_LDAP.string_collection;
          v_search_results       DBMS_LDAP.MESSAGE;
          v_entry                DBMS_LDAP.MESSAGE;
          v_distinguished_name   VARCHAR2(256);
          v_dn_pieces            DBMS_LDAP.string_collection;
          v_values               DBMS_LDAP.string_collection;
      
      BEGIN 
      
      
          --初始化session
          v_session := DBMS_LDAP.init(hostname => '180.76.186.73', portnum => DBMS_LDAP.port);
      
      
          --binding , 如果不进行此操作,则必须开启LDAP匿名访问权限
          v_result := DBMS_LDAP.simple_bind_s(
                      ld => v_session, 
                      dn => 'cn=admin,dc=dezohty,dc=com', 
                      passwd => 'adminpw');   
      
          --指定搜索的属性,1.1 = 不返回属性信息
          v_search_attrs(1) := '1.1';
          --搜索 , FILTER 指定过滤器  
          --  orjectclass=* 表示返回所有结果
          --  uid=chaofeng.li 表示返回uid = chaofeng.li的条目 , uid在LDAP中是唯一的
          --  DBMS_LDAP.scope_base        =>  只搜索指定的base
          --  DBMS_LDAP.scope_onelevel    =>  搜索指定的base及base下一level的entities
          --  DBMS_LDAP.scope_subtree     =>  搜索整个base树结构
          --  attronly  0 表示属性和属性值均返回  1 表示只返回属性名
          --  search_s 普通搜索  search_st 指定超时时间  tv =>     v_timeout          DBMS_LDAP.timeval
          v_result :=
              DBMS_LDAP.search_s(ld         => v_session,
                                 base       => 'ou=dc=dezohty,dc=com',
                              --    scope      => DBMS_LDAP.scope_base,
                                 scope      => DBMS_LDAP.scope_onelevel,
                              --    scope      => DBMS_LDAP.scope_subtree,                       
                                 filter     => 'objectclass=*',
                                 attrs      => v_search_attrs,
                                 attronly   => NULL,
                                 res        => v_search_results);
      
          
          -- 获得结果总数
          v_result := DBMS_LDAP.count_entries(v_session, v_search_results);
          DBMS_OUTPUT.put_line(v_result) ;
      
      
          v_entry := DBMS_LDAP.first_entry(v_session, v_search_results);
      
          -- 遍历查询结果
          while v_entry is not null 
          LOOP
              v_distinguished_name := DBMS_LDAP.get_dn(v_session, v_entry);
              DBMS_OUTPUT.put_line('DN: ' || v_distinguished_name);
      
      
          -- 搜索属性值
              FOR i IN 1 .. v_search_attrs.COUNT
              LOOP
                 v_values := DBMS_LDAP.get_values(v_session, v_entry, v_search_attrs(i));
          
                 IF v_values.COUNT > 0
                 THEN
                     FOR j IN v_values.FIRST .. v_values.LAST
                     LOOP
                         DBMS_OUTPUT.put_line(v_search_attrs(i) || ' : ' || v_values(j));
                     END LOOP;
                 ELSE
                     DBMS_OUTPUT.put_line(v_search_attrs(i) || ' not found');
                 END IF;
              END LOOP;
      
        		-- 切分DN片段
          	-- v_dn_pieces := DBMS_LDAP.explode_dn(dn => v_distinguished_name, notypes => 0);
      
          	-- FOR i IN v_dn_pieces.FIRST .. v_dn_pieces.LAST
          	-- LOOP
          	--     DBMS_OUTPUT.put_line(i || ': ' || v_dn_pieces(i));
          	-- END LOOP;
      
      
      
      
              v_entry := DBMS_LDAP.next_entry(v_session, v_entry );
      
          end loop ;
      
        
       
          v_result := DBMS_LDAP.unbind_s(v_session);
      END;
      /
    2. 查询示例

      base       => 'ou=dc=dezohty,dc=com', 搜索结果示例:

      --  DBMS_LDAP.scope_base  =>  只搜索指定的base

       
      --  DBMS_LDAP.scope_onelevel    =>  搜索指定的base及base下一level的entities

       

      --  DBMS_LDAP.scope_subtree     =>  搜索整个base树结构

        

  4. 修改数据

    1. 插入

      --本例LDAP服务器为AD域
      DECLARE
          v_session      DBMS_LDAP.session;
          v_result       PLS_INTEGER;
          v_attributes   DBMS_LDAP.mod_array;
          v_strings      DBMS_LDAP.string_collection;
      BEGIN
          DBMS_LDAP.use_exception := FALSE;
          v_session := DBMS_LDAP.init(hostname => '10.7.37.10', portnum => DBMS_LDAP.port);
      
          v_result :=
              DBMS_LDAP.simple_bind_s(ld       => v_session,
                                      dn       => 'CN=chaofeng li,CN=Users,DC=cf,DC=com',
                                      passwd   => '!Beijing');
      --                                dn       => 'CN=test_name6 li,CN=Users,DC=cf,DC=com',
      --                                passwd   => '!Beijing');
      
          IF v_result != DBMS_LDAP.success
          THEN
              DBMS_OUTPUT.put_line('Bind Result: ' || v_result || ' ' || DBMS_LDAP.err2string(v_result));
          ELSE
              v_attributes := DBMS_LDAP.create_mod_array(num => 4);
      
              v_strings(1) := '123461';
              DBMS_LDAP.populate_mod_array(modptr     => v_attributes,
                                           mod_op     => DBMS_LDAP.mod_add,
                                           mod_type   => 'sAMAccountName',  --sAMAccountName是唯一的
                                           modval     => v_strings);
      
              v_strings(1) := 'user';
              DBMS_LDAP.populate_mod_array(modptr     => v_attributes,
                                           mod_op     => DBMS_LDAP.mod_add,
                                           mod_type   => 'objectclass',
                                           modval     => v_strings);
      
              v_strings(1) := '544';
              DBMS_LDAP.populate_mod_array(modptr     => v_attributes,
                                           mod_op     => DBMS_LDAP.mod_add,
                                           mod_type   => 'userAccountControl',  --544表示ldap中enable , 546表示disable
                                           modval     => v_strings);
                                           
              v_strings(1) := '!Beijing';
              DBMS_LDAP.populate_mod_array(modptr     => v_attributes,
                                           mod_op     => DBMS_LDAP.mod_add,
                                           mod_type   => 'userpassword',  --设置用户密码,必须符合密码规则, 否则即使添加成功也不会认证
                                           modval     => v_strings);        
      --
      --        v_strings(1) :=
      --            '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myserver)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=myservice)))';
      --        DBMS_LDAP.populate_mod_array(modptr     => v_attributes,
      --                                     mod_op     => DBMS_LDAP.mod_add,
      --                                     mod_type   => 'orclNetDescString',
      --                                     modval     => v_strings);
      
              v_result :=
                  DBMS_LDAP.add_s(ld        => v_session,
                                  entrydn   => 'cn=test_name6,CN=Users,DC=cf,DC=com',  -- cn唯一
                                  modptr    => v_attributes);
      
              IF v_result = DBMS_LDAP.success
              THEN
                  DBMS_OUTPUT.put_line('Add successful');
              ELSE
                  DBMS_OUTPUT.put_line('Add Result: ' || v_result || ' ' || DBMS_LDAP.err2string(v_result));
              END IF;
      
              DBMS_LDAP.free_mod_array(modptr => v_attributes);
              v_result := DBMS_LDAP.unbind_s(v_session);
          END IF;
      END;
      /
    2. 删除


      DBMS_LDAP没有提供批量删除功能,如果需要批量删除,则需要循环执行删除命令

              v_result := DBMS_LDAP.delete_s(ld => v_session, entrydn => 'cn=test_name,cn=OracleContext,dc=example,dc=net');
      
    3. 修改

      DBMS_LDAP.populate_mod_array(modptr     => v_attributes,
                                           mod_op     => DBMS_LDAP.mod_replace,
                                           mod_type   => 'orclNetDescString',
                                           modval     => v_strings);
      v_result :=
                  DBMS_LDAP.modify_s(ld        => v_session,
                                     entrydn   => 'cn=test_name,cn=OracleContext,dc=example,dc=net',
                                     modptr    => v_attributes);


  • No labels