Иностранные символы и LDAP. Какую кодировку / кодировку ожидает LDAP?

я разбираю XML, с simplexml_load_string() и использование данных в нем для обновления объектов Active Directory (AD) через LDAP.

пример 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() найти одного пользователя, а затем приступить к изменению их свойств. Накачка вышеуказанных значений прямо в AD, используя LDAP, приведет к появлению некоторых довольно искаженных символов.

например: 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 покажет правильные символы, но веб-браузеры показывают то же самое, что и AD.

что происходит? Должен ли я смотреть на что-то другое, например. URL-АДРЕС кодирование? Я надеюсь, что это просто ошибка с моей стороны.

EDIT: Я ввел эти символы с помощью ad admin GUI, чтобы увидеть, как они выйдут. Я могу прочитать их через LDAP. Правильные символы отображаются в браузере. curl-ing через 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 server: Windows 2003

обновление: Через несколько месяцев, я не смог найти ответ/решение этой проблемы. В конце концов, я пошел с заменой персонажи к их не акцентированному эквиваленту (не идеальному, Я знаю).

4 ответов


вы используете LDAP v3?

ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);

LDAPv3 поддерживает UTF-8 по умолчанию, который он ожидает, что запросы и ответы будут по умолчанию. Смотрите здесь: http://technet.microsoft.com/en-us/library/cc961766.aspx


мне удалось добавить иностранные символы в LDAP с двумя шагами:

  • Добавить пользователя только с символами ASCII (iconv "ASCII//TRANSLIT")

  • использовать ldapmodify для обновления полей UTF-8 символами

LDAPv3-UTF-8, но инструмент, который я использовал (от smbldap-tools) не справлялся с этим должным образом.


вот решение, которое сработало для меня. Делайте следующие вещи:

1.) Сначала убедитесь, что вы используете протокол LDAP версии 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}}0"; 
    }
    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, затем нужно расшифровать его перед отправкой

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

этот код работал для меня, когда я предоставьте немецкие Umlauts в пароле:äüößÄÜ etc...


еще одна вещь, чтобы упомянуть для тех, кто натыкается на это:

Если ваш текст уже находится в UTF-8, Не пытайтесь его перекодировать. Обратите внимание на следующие замечания на странице doc для utf8_encode. Повторное кодирование уже закодированной строки приведет к искажению текста. Кроме того, функция позволяет использовать только одну конкретную кодировку для другой.

Вы можете легко проверить, нужно ли UTF-8 кодировать строку, делая что-то например:

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

Что касается символов, которые не отображаются правильно на веб-странице, но они находятся на CLI, убедитесь, что вы устанавливаете правильную кодировку в своих заголовках:

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