外来字符和LDAP。 LDAP期望的编码/字符集是什么?

时间:2012-06-14 14:32:56

标签: php encoding active-directory ldap

我使用simplexml_load_string()解析XML,并使用其中的数据通过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
  • 正在运行生产:Red Hat 6 - PHP 5.4.3
  • AD服务器:Windows 2003

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

4 个答案:

答案 0 :(得分:6)

您使用的是LDAP v3吗?

ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);

默认情况下,LDAPv3支持UTF-8,默认情况下它会要求请求和响应。见这里:http://technet.microsoft.com/en-us/library/cc961766.aspx

答案 1 :(得分:2)

Here is solution that worked for me. Do following things:

1.) First make sure you are using LDAP protocol version 3 which is using "UTF-8" by default:

ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);

2.) If you want to change user's password, than make sure that "use TLS" option is set to true and use SSL to false.

ldap_start_tls($ldapConnection);

3.) I used port number 389.

4.) Use PHP function ldap_mod_replace to replace user's password.

5.) Use the following function to encode your $password:

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

6.) Use the following logic to change user's password:

$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.) Please note that function encodePassword will encode your $password to UTF-8 encoding. If your password is UTF-8 encoded, then your have to decode it before sending it to the encodePassword function. That is why I wrote the line:

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

This code worked for me when I provide german Umlauts in password: äüößÄÜ etc...

答案 2 :(得分:1)

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

  • 仅使用ASCII字符添加用户(iconv&#34; ASCII // TRANSLIT&#34;)

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

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

答案 3 :(得分:0)

对于那些绊脚石的人来说,还有一件事要提到:

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

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

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

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

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