外语字符和 LDAP.LDAP 需要什么编码/字符集


Foreign characters and LDAP. What encoding/charset does LDAP expect?

我正在解析XML,simplexml_load_string(),并使用其中的数据通过LDAP更新Active Directory(AD)对象。

示例 XML(简体):

<?xml version="1.0" encoding="UTF-8"?>
<users>
    <user>Bìlbö Bággįnš</user>
    <user>Gãńdåłf Thê Gręât</user>
    <user>Śām Wīšë</user>
</users>

我首先运行一个ldap_search()来查找单个用户,然后继续更改其属性。使用 LDAP 将上述值直接泵入 AD,将导致出现一些非常混乱的角色。

例如:Bìlbö BággįnÅ¡

我尝试了以下功能,但无济于事:

utf8_encode($str);
utf8_decode($str);
iconv("UTF-8", "ISO-8859-1//TRANSLIT", $str);
iconv("UTF-8", "ASCII//TRANSLIT", $str);
iconv("UTF-8", "T.61", $str);

理想情况下,我不想进行任何这些字符串转换。UTF-8 应该没问题吧?!

我还注意到以下几点:我已经打印出这些值,看看它们是如何出来的。在 CLI 中卷曲脚本将显示正确的字符,但 Web 浏览器显示的字符与 AD 相同。

这是怎么回事?我应该看别的东西,例如。网址编码?我希望这归结为我的一个简单的错误。

编辑:我使用 AD 管理员 GUI 输入这些字符,看看它们会如何出现。我可以通过LDAP很好地阅读它们。在浏览器中显示正确的字符。通过 CLI 卷曲将显示问号而不是外来字符。将这些返回值之一传递到 mb_detect_encoding() 将返回 UTF-8。

我决定立即修改同一个对象,不写入新字符串,而只是反转现有值并保存对象。这工作正常 - 我在 AD 中看到正确的值(反转)。

  • 在 Mac OS X 10.7 Lion 上开发 - PHP 5.4.3
  • 生产版本: 红帽 6 - PHP 5.4.3
  • AD服务器:视窗2003

更新:几个月后,我无法找到这个问题的答案/解决方案。最后,我选择将字符替换为非重音等效字符(我知道这并不理想)。

您是否正在使用 LDAP v3?

ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);

LDAPv3 默认支持 UTF-8,它希望请求和响应默认为 UTF-8。看这里: http://technet.microsoft.com/en-us/library/cc961766.aspx

这是对我有用的解决方案。执行以下操作:

1.) 首先确保您使用的是 LDAP 协议版本 3,该版本 3 正在使用 默认为"UTF-8":

ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);

2.)如果要更改用户的密码,请确保将"使用TLS"选项设置为true并使用SSL false

ldap_start_tls($ldapConnection);

3.) 我使用了端口号 389 .

4.) 使用PHP函数ldap_mod_replace替换用户密码。

5.) 使用以下函数对$password进行编码:

public function encodePassword($password)
{
    $password="'"".$password."'"";
    $encoded="";
    for ($i=0; $i <strlen($password); $i++){ 
        $encoded.="{$password{$i}}'000"; 
    }
    return $encoded;
}

6.) 使用以下逻辑更改用户密码:

$password="test";
if(mb_detect_encoding($password) == 'UTF-8')
{
    $password = utf8_decode($password);
}
$add=array();
$add["unicodePwd"][0] = encodePassword($password);
$result = @ldap_mod_replace($ldapConnection, $userDn, $add);
if ($result === false){
    //your action
}
else{
    //Your action
}

7.) 请注意,函数encodePassword将对您的编码 $password UTF-8 编码。如果您的密码是 UTF-8 编码的, 然后你必须在将其发送到 encodePassword功能。这就是为什么我写了这行:

if(mb_detect_encoding($password) == 'UTF-8')
{
    $password = utf8_decode($password);
}

当我在密码中提供德语变音符号时,此代码对我有用:äüößÄÜ等...

我设法通过两个步骤在LDAP中添加外语字符:

  • 仅使用 ASCII 字符添加用户 (iconv "ASCII//TRANSLIT")

  • 使用 ldapmodify 更新具有 UTF-8 字符的字段

LDAPv3 是 UTF-8,但我使用的工具(来自 smbldap-tools )没有正确处理它。

对于那些

偶然发现这一点的人来说,还有一件事要提:

如果您的文本已经是 UTF-8,请不要尝试重新编码它。请注意文档页面上的以下备注,以供utf8_encode使用。重新编码已编码的字符串将导致文本出现乱码。此外,该函数仅允许将一种特定编码编码到另一种编码。

您可以通过执行以下操作轻松测试是否需要对字符串进行 UTF-8 编码:

if (!preg_match('//u', $value)) {
    // do your encoding process...
}

关于网页上未正确显示的字符,但它们在 CLI 上,请确保在标题中设置正确的字符集:

header('Content-type: text/html; charset=utf-8');