如何通过PHP移动eDirectory条目?

3
我有这个LDAP条目:
cn=blah,ou=apples,ou=people,dc=yay,dc=edu
我需要将该条目移动到:
cn=blah,ou=oranges,ou=people,dc=yay,dc=edu
我的脚本都是PHP,所以我一直在尝试使用php.net/ldap_rename。
ldap_rename($connection, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", "ou=oranges,ou=people,dc=yay,dc=edu", true);

不起作用。它返回false。

http://us2.php.net/manual/en/function.ldap-rename.php#82393这个评论提到eDirectory希望将父级保留为NULL。就像这样:

ldap_rename($connection, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", NULL, true);

这会返回TRUE,但实际上不会移动该条目。这并不奇怪,因为它没有更改父级...我相信它可以将cn = blah更改为其他内容...

我考虑过删除该条目并重新创建它。但这是一个痛苦的方法。编写和运行LDIF文件也很麻烦。

那么,在php中,如何将输入从一个OU移动到另一个OU,而不需要付出其他两个选项的代价?

我的运行环境:

  • Ubuntu 12.04 LTS
  • PHP 5.3.10
  • eDirectory 8.8位于SLES 11上

编辑

所以,我找到了这个:

modrdn更改类型无法将条目移动到完全不同的子树。要将条目移动到完全不同的分支,您必须使用旧条目的属性在替代子树中创建一个新条目,然后删除旧条目。

来自http://www.centos.org/docs/5/html/CDS/ag/8.0/Creating_Directory_Entries-LDIF_Update_Statements.html

我发现了几个类似语句的页面。

所以看起来我必须创建一个新条目,复制属性,然后删除旧条目。就像我上面提到的第二种痛苦的选择一样。


你能告诉我你正在运行的LDAP版本吗? - Ohgodwhy
所述评论明确讨论了重命名而不是移动条目。因此,它在这里不适用。您是否尝试在第三个参数中给出完整的dn?并且您确定绑定到LDAP的用户具有足够的权限吗? - heiglandreas
LDAP v3。在代码中我之前显式地设置了协议。我正在测试的用户是目录的主要管理员。因此,它具有正确的权限。 - David R.
刚刚尝试将完整的新dn传递给第三个参数。ldap_rename返回true,但eDirectory没有移动该条目。 - David R.
3个回答

2

好的,我最终采用了“创建新条目,删除旧条目”的方法。我仍然认为我之前有另一种方法可行,但我想不起来是什么了。因此,这里是一个基本的移动函数。

function move($connection, $ldapEntryReference, $new_dn){        
    //First, get the values of the current attributes.
    $attributes = array(); //start attributes array
    $firstattr = ldap_first_attribute($connection, $ldapEntryReference);
    $value = ldap_get_values($connection, $ldapEntryReference, $firstattr);
    $attributes[$firstattr] = $value;
    while($attr = ldap_next_attribute($connection, $ldapEntryReference)) {
        if (strcasecmp($attr, 'ACL') !== 0) { //We don't want ACL attributes since 
                                              //eDir/ldap should deal with them for us.
            if (strcasecmp($attr, 'jpegPhoto') === 0) {
                //binary values need to use the ldap_get_values_len function.
                $value = ldap_get_values_len($this->connection, $ldapEntryReference, $attr);
            } else {
                $value = ldap_get_values($this->connection, $ldapEntryReference, $attr);
            }
            $attributes[$attr] = $value;
        }
    }
    //Create a new entry array with the values.
    $entry = array(); //start entry array.
    foreach($attributes as $key => $value) {
        foreach($value as $key2 => $value2) {
            if (strcasecmp($key2, 'count') !== 0) {//get rid of 'count' indexes
                                                   //ldap_add chokes on them.
                $entry[$key][$key2] = $value2;
            }
        }
    }
    //Add the new entry.
    if (ldap_add($connection, $new_dn, $entry)) {
        //Delete the old entry.
        if (ldap_delete($connection, ldap_get_dn($connection, $ldapEntryReference)) {
            return true;
        } else {
            return false;
        }
    } else {
        return false; 
    }
}

希望这能帮助到某个人,某时某刻。

请注意函数的倒数第五行缺少一个右括号。应该是 if (ldap_delete($connection, ldap_get_dn($connection, $ldapEntryReference))) { - Tim Dearborn

0

试试这个:

ldap_rename($ldapconn, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", "ou=oranges,ou=people,dc=yay,dc=edu", true);

0

实际上,没有必要在 eDir 中重新创建。在运行 IDM 的环境中进行重新创建会导致问题,因为对象将具有新的 GUID,IDM 引擎将不会将事件视为真正的“移动”。

以下代码可以很好地移动用户(已在 eDir 8.8.x 和 eDir 9.x 上测试):

$olduserdn = "cn=userid,ou=container1,o=org";
$newdestdn = "ou=container2,o=org";
if (preg_match('/^(cn=[A-Za-z0-9]+)\,(.+)/i', $olduserdn, $rdnmatches))
{
    if (ldap_rename($ldapconn, $olduserdn, $rdnmatches[1], $newdestdn, TRUE))
    {
        print("Moved $olduserdn to $rdnmatches[1],$newdestdn");
    }
    else
    {
        print("Failed move because " . ldap_error($ldapconn));
    }
}

不要忘记留出一点时间进行复制...

同时考虑修改/移动对象的限制,这些对象仍在从先前的移动事件中进行复制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接