2011-12-19 42 views
12

Tôi đang cố gắng thêm một số người dùng vào Ldap DB nhưng tôi gặp một số lỗi (cú pháp dn không hợp lệ) khi tôi sử dụng một số ký tự đặc biệt như ",.". Tôi cần một chức năng để thoát khỏi tất cả các nhân vật. Tôi cố gắng preg_quote nhưng tôi nhận được một số lỗi trong một số trường hợp.Chức năng PHP ldap_add để thoát các ký tự đặc biệt trong cú pháp DN

Cảm ơn trước

Code:

$user = 'Test , Name S.L'; 

    if(!(ldap_add($ds, "cn=" . $user . ",".LDAP_DN_BASE, $info))) { 

      include 'error_new_account.php'; 

    } 

Trả lời

25

EDIT tháng 1 năm 2013: thêm hỗ trợ cho thoát hàng đầu/dấu không gian trong chuỗi DN, mỗi RFC 4514. Nhờ có Eugenio để chỉ ra vấn đề này.

EDIT 2014: I added this function to PHP 5.6. Đoạn mã dưới đây bây giờ là một sự thay thế tương tự cho các phiên bản PHP trước đó.

if (!function_exists('ldap_escape')) { 
    define('LDAP_ESCAPE_FILTER', 0x01); 
    define('LDAP_ESCAPE_DN',  0x02); 

    /** 
    * @param string $subject The subject string 
    * @param string $ignore Set of characters to leave untouched 
    * @param int $flags Any combination of LDAP_ESCAPE_* flags to indicate the 
    *     set(s) of characters to escape. 
    * @return string 
    */ 
    function ldap_escape($subject, $ignore = '', $flags = 0) 
    { 
     static $charMaps = array(
      LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"), 
      LDAP_ESCAPE_DN  => array('\\', ',', '=', '+', '<', '>', ';', '"', '#'), 
     ); 

     // Pre-process the char maps on first call 
     if (!isset($charMaps[0])) { 
      $charMaps[0] = array(); 
      for ($i = 0; $i < 256; $i++) { 
       $charMaps[0][chr($i)] = sprintf('\\%02x', $i);; 
      } 

      for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_FILTER]); $i < $l; $i++) { 
       $chr = $charMaps[LDAP_ESCAPE_FILTER][$i]; 
       unset($charMaps[LDAP_ESCAPE_FILTER][$i]); 
       $charMaps[LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr]; 
      } 

      for ($i = 0, $l = count($charMaps[LDAP_ESCAPE_DN]); $i < $l; $i++) { 
       $chr = $charMaps[LDAP_ESCAPE_DN][$i]; 
       unset($charMaps[LDAP_ESCAPE_DN][$i]); 
       $charMaps[LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr]; 
      } 
     } 

     // Create the base char map to escape 
     $flags = (int)$flags; 
     $charMap = array(); 
     if ($flags & LDAP_ESCAPE_FILTER) { 
      $charMap += $charMaps[LDAP_ESCAPE_FILTER]; 
     } 
     if ($flags & LDAP_ESCAPE_DN) { 
      $charMap += $charMaps[LDAP_ESCAPE_DN]; 
     } 
     if (!$charMap) { 
      $charMap = $charMaps[0]; 
     } 

     // Remove any chars to ignore from the list 
     $ignore = (string)$ignore; 
     for ($i = 0, $l = strlen($ignore); $i < $l; $i++) { 
      unset($charMap[$ignore[$i]]); 
     } 

     // Do the main replacement 
     $result = strtr($subject, $charMap); 

     // Encode leading/trailing spaces if LDAP_ESCAPE_DN is passed 
     if ($flags & LDAP_ESCAPE_DN) { 
      if ($result[0] === ' ') { 
       $result = '\\20' . substr($result, 1); 
      } 
      if ($result[strlen($result) - 1] === ' ') { 
       $result = substr($result, 0, -1) . '\\20'; 
      } 
     } 

     return $result; 
    } 
} 

Vì vậy, bạn sẽ làm gì:

$user = 'Test , Name S.L'; 
$cn = ldap_escape($user, '', LDAP_ESCAPE_DN); 
if (!ldap_add($ds, "cn={$cn}," . LDAP_DN_BASE, $info)) { 
    include 'error_new_account.php'; 
} 
+0

Cảm ơn bạn rất nhiều, chức năng tốt đẹp. – Sbml

+0

@daverandom bạn nên thêm vào các ký tự để thoát cũng là dấu cách (nếu chúng là ký tự đầu tiên hoặc cuối cùng của một giá trị thuộc tính), tôi có đúng không? Ngoài ra, dấu # phải được thoát chỉ khi đó là ký tự đầu tiên của giá trị thuộc tính. http://www-03.ibm.com/systems/i/software/ldap/underdn.html – Eugenio

+0

@Eugenio Thú vị, bạn có biết đó là tiêu chuẩn LDAP hoặc IBM cụ thể không?Tôi chưa bao giờ thấy những quy định đó ở bất cứ nơi nào trước đây. Các tài liệu tiêu chuẩn DAP/LDAP rất dài và rất trừu tượng, rất khó để tìm thấy ít cốm về thông tin như thế - và tôi đang gặp khó khăn khi đặt tay lên chúng một lần nữa: S – DaveRandom

1

Những nhân vật phải thoát là một phần của các dữ liệu của một tên phân biệt hoặc tên phân biệt tương đối. Thoát ký tự (như trong tất cả LDAP) với một chữ số thập lục phân 2 dấu gạch chéo ngược, chẳng hạn như \2a. Bất cứ điều gì khác sẽ không phù hợp với các tài liệu tiêu chuẩn của cơ thể. Xem RFC4514 để biết thêm thông tin cụ thể về chuỗi đại diện của các tên phân biệt.

2

PHP 5.6 Beta phát hành ldap_escape() hoạt động gần đây và có hiệu lực, Tuy nhiên, phiên bản này chưa sẵn sàng để sản xuất, bạn có thể sử dụng nó cho mục đích phát triển của bạn.

2

Chỉ cần lưu ý nếu bạn chưa sử dụng PHP 5.6, bạn có thể sao chép chính xác chức năng PHP 5.6 ldap_escape() sử dụng các phương pháp tôi đã tạo bên dưới, lưu ý điều này có nghĩa là sử dụng trong lớp học. Câu trả lời ở trên không thực hiện chính xác như chức năng ldap_escape, vì nó không thoát khỏi tất cả các ký tự thành chuỗi ký tự hex nếu không có cờ nào được cung cấp, vì vậy điều này sẽ phù hợp hơn để thay thế cho các phiên bản trước của PHP, theo cách hướng đối tượng.

Tôi đã ghi lại mọi dòng để hiểu rõ hơn về những gì đang diễn ra. Cuộn xuống cho đầu ra.

Methods (Tương thích với PHP 5 hoặc cao hơn):

/** 
* Escapes the inserted value for LDAP. 
* 
* @param string $value The value to escape 
* @param string $ignore The characters to ignore 
* @param int $flags The PHP flag to use 
* 
* @return bool|string 
*/ 
public function escapeManual($value, $ignore = '*', $flags = 0) 
{ 
    /* 
    * If a flag was supplied, we'll send the value 
    * off to be escaped using the PHP flag values 
    * and return the result. 
    */ 
    if($flags) { 
     return $this->escapeWithFlags($value, $ignore, $flags); 
    } 

    // Convert ignore string into an array 
    $ignores = str_split($ignore); 

    // Convert the value to a hex string 
    $hex = bin2hex($value); 

    /* 
    * Separate the string, with the hex length of 2, 
    * and place a backslash on the end of each section 
    */ 
    $value = chunk_split($hex, 2, "\\"); 

    /* 
    * We'll append a backslash at the front of the string 
    * and remove the ending backslash of the string 
    */ 
    $value = "\\" . substr($value, 0, -1); 

    // Go through each character to ignore 
    foreach($ignores as $charToIgnore) 
    { 
     // Convert the characterToIgnore to a hex 
     $hexed = bin2hex($charToIgnore); 

     // Replace the hexed variant with the original character 
     $value = str_replace("\\" . $hexed, $charToIgnore, $value); 
    } 

    // Finally we can return the escaped value 
    return $value; 
} 

/** 
* Escapes the inserted value with flags. Supplying either 1 
* or 2 into the flags parameter will escape only certain values 
* 
* 
* @param string $value The value to escape 
* @param string $ignore The characters to ignore 
* @param int $flags The PHP flag to use 
* @return bool|string 
*/ 
public function escapeWithFlags($value, $ignore = '*', $flags = 0) 
{ 
    // Convert ignore string into an array 
    $ignores = str_split($ignore); 

    $escapeFilter = ['\\', '*', '(', ')']; 
    $escapeDn = ['\\', ',', '=', '+', '<', '>', ';', '"', '#']; 

    switch($flags) 
    { 
     case 1: 
      // Int 1 equals to LDAP_ESCAPE_FILTER 
      $escapes = $escapeFilter; 
      break; 
     case 2: 
      // Int 2 equals to LDAP_ESCAPE_DN 
      $escapes = $escapeDn; 
      break; 
     case 3: 
      // If both LDAP_ESCAPE_FILTER and LDAP_ESCAPE_DN are used 
      $escapes = array_merge($escapeFilter, $escapeDn); 
      break; 
     default: 
      // Customize your own default return value 
      return false; 
    } 

    foreach($escapes as $escape) 
    { 
     // Make sure the escaped value isn't inside the ignore array 
     if(! in_array($escape, $ignores)) 
     { 
      $hexed = chunk_split(bin2hex($escape), 2, "\\"); 

      $hexed = "\\" . substr($hexed, 0, -1); 

      $value = str_replace($escape, $hexed, $value); 
     } 
    } 

    return $value; 
} 

thử nghiệm (lưu ý rằng hằng LDAP_ESCAPE chỉ có sẵn trong PHP 5.6):

// Value to escape 
$value = 'testing=+<>"";:#()*\x00'; 

$php = ldap_escape($value, $ignore = '*'); 

$man = $this->escapeManual($value, $ignore = '*'); 

echo $php; // \74\65\73\74\69\6e\67\3d\2b\3c\3e\22\22\3b\3a\23\28\29*\5c\78\30\30 
echo $man; // \74\65\73\74\69\6e\67\3d\2b\3c\3e\22\22\3b\3a\23\28\29*\5c\78\30\30 


$php = ldap_escape($value, $ignore = '*', LDAP_ESCAPE_DN); 

$man = $this->escapeManual($value, $ignore = '*', LDAP_ESCAPE_DN); 

echo $php; // testing\3d\2b\3c\3e\22\22\3b:\23()*\5cx00 
echo $man; // testing\3d\2b\3c\3e\22\22\3b:\23()*\5cx00 


$php = ldap_escape($value, $ignore = '*', LDAP_ESCAPE_FILTER); 

$man = $this->escapeManual($value, $ignore = '*', LDAP_ESCAPE_FILTER); 

echo $php; // testing=+<>"";:#\28\29*\5cx00 
echo $man; // testing=+<>"";:#\28\29*\5cx00 

Github Gist liên kết : https://gist.github.com/stevebauman/0db9b5daa414d60fc266

Các vấn đề liên quan