iT邦幫忙

0

XAMPP 的 PHP 無法使用 LDAP 進行 AD 帳號驗證

  • 分享至 

  • xImage

系統環境:Windows 10
開發平台:XAMPP 8.2.12
問題描述:網路上查詢如何透過PHP LDAP進行AD帳號來驗證,發現已在PHP.INI裡面新增或啟用 extension=php_ldap.dll 或 extension=ldap,都無法LDAP連線AD
執行下述程式只會顯示 LDAP BINDING FAILED
不知道各位前輩是否有遇到這個問題?
還望前輩指教,謝謝。
測試LDAP程式碼:

$username   = 'ldapadmin';
$password   = 'Ldap_admin';
$server = '192.168.32.4';
$domain = '@demo.com.tw';
$port       = 389;
$ldap_connection = ldap_connect($server, $port);
if (! $ldap_connection)
{
    echo '
LDAP SERVER CONNECTION FAILED

';
    exit;
}
// Help talking to AD
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap_connection, LDAP_OPT_REFERRALS, 0);
$ldap_bind = @ldap_bind($ldap_connection, $username.$domain, $password);
if (! $ldap_bind)
{
    echo '
LDAP BINDING FAILED

';
    exit;
}
// You can work now!!!
ldap_close($ldap_connection);
連城 iT邦新手 4 級 ‧ 2024-03-04 14:06:05 檢舉
你試試看在if 判斷之前dd(ldap_bind)
看看內容是甚麼

我有點懷疑 "@"ldap_bind 是不是寫錯

另外如果有使用框架的話
ldaprecord 可以考慮一下
我目前這個套件內部環境可以驗證成功
感謝連城大大的回覆
1. 這邊方才測試了一下,我不確定$ldap_bind = @ldap_bind($ldap_connection, $username.$domain, $password);這段是否有問題,不過這字串我有echo $username$domain 以及 $password 這兩個變數,內容是沒有錯的。不過我echo不出$ldap_connection這個內容
2.目前沒有使用框架,方便大大提供整個程式範本讓我測試看看嗎?
謝謝。
謝謝連成大大,已解決。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
Ray
iT邦大神 1 級 ‧ 2024-03-03 21:01:08
看更多先前的回應...收起先前的回應...

抱歉,漏了描述

  1. 這台Windows 10已經有加入這個AD裡面。
  2. 謝謝Ray大神的回覆,剛剛有啟用LDP工具,測試是有正常連線的(如下圖)。
    https://ithelp.ithome.com.tw/upload/images/20240303/20006167fKYfK57YzK.jpg
Ray iT邦大神 1 級 ‧ 2024-03-04 07:24:09 檢舉

你的 ldp 測試是連上 192.168.90.211, 但你的程式卻是去連: 192.168.32.4?
有試過用 ldp 去連這台 192.168.32.4 嗎?

若改成這樣呢:

<?php
$ldap_host = 'ldap://192.168.90.211';
$ldap_port = 389;
$ldap_user = 'cn=admin,dc=example,dc=com'; // LDAP管理員用戶名稱
$ldap_pass = 'your_admin_password'; // LDAP管理員密碼

$ldap_conn = ldap_connect($ldap_host, $ldap_port);

if (!$ldap_conn) {
    echo "無法連線到 ldap 服務器\n";
    exit;
}

// 绑定LDAP管理員用户
$ldap_bind = ldap_bind($ldap_conn, $ldap_user, $ldap_pass);

if (!$ldap_bind) {
    echo "LDAP管理員綁定失敗\n";
    exit;
}

echo "成功連接並綁定\n";
?>

您好,抱歉造成Ray大神的誤解,小弟說明一下

  1. 當初提供的程式碼我有修改了連線LDP的資料,實際上程式碼裡面用的是192.168.90.211這個沒錯,帳號資料也是這個測試環境的帳號密碼。所以LDP截圖資料是正確的,程式裡面連線的標的也是沒有問題。
  2. 這個測試開發環境,目前就是Win10加入了192.168.90.211這個網域,使用的也是這個網域上的帳號進行登入,所以AD的狀態應該不是問題。就是查了很久覺得不知道是否因為XAMPP的版本問題才產生無法正常連線LDAP的情況。
Ray iT邦大神 1 級 ‧ 2024-03-04 19:44:30 檢舉

那你的 username 有改用上面範例中的 DN 表達式嗎?

$ldap_user = 'cn=admin,dc=example,dc=com';

LDAP 跟你的電腦有沒有加入 AD 無關, 沒加入 AD 的電腦同樣可以取得 LDAP 查詢內容.

但是, LDAP 只能綁定 DN 格式輸入的 username, 不是你在 AD 中使用的 uid 格式.

感謝Ray大神回覆,這邊我看程式的邏輯在帳號的部分應該是拼成網域帳號的樣子
$ldap_bind = @ldap_bind($ldap_connection, $username.$domain, $password);
應該會變成 $ldap_bind = @ldap_bind($ldap_connection, ldapadmin@black.vhoffice.com, Ldap_admin); 這樣

此外之前有測試過dc=black,dc=vhoffice,dc=com這個方式,也是不行。

感謝Ray大神第二個回覆內容程式碼小弟現在才反應過來,測試後的結果還是失敗
程式碼內容我依照現在測試環境調整如下:

<?php
$ldap_host = 'ldap://192.168.90.211';
$ldap_port = 389;
$ldap_user = 'cn=ldapadmin,dc=black,dc=vhoffice,dc=com'; // LDAP管理員用戶名稱
$ldap_pass = 'Rmbi_6894'; // LDAP管理員密碼

$ldap_conn = ldap_connect($ldap_host, $ldap_port);

if (!$ldap_conn) {
    echo "無法連線到 ldap 服務器\n";
    exit;
}

// 绑定LDAP管理員用户
$ldap_bind = ldap_bind($ldap_conn, $ldap_user, $ldap_pass);

if (!$ldap_bind) {
    echo "LDAP管理員綁定失敗\n";
    exit;
}

echo "成功連接並綁定\n";
?>

錯誤畫面如下圖
https://ithelp.ithome.com.tw/upload/images/20240304/20006167UxQZlhnsKX.jpg

Ray iT邦大神 1 級 ‧ 2024-03-04 21:34:21 檢舉

後面的錯誤寫:

...Stronger authentication required...

此錯誤代表:
AD Server 要求你必須透過 SSL 加密才能進行帳號驗證.

這有兩種解法:

  1. 改用 ldaps 加密協定取代 ldap 和 port:
$ldap_host = 'ldaps://192.168.90.211';
$ldap_port = 636;
  1. Bind 之前先強制取消 SSL (但不一定有效):
putenv('LDAPTLS_REQCERT=never');

非常感謝Ray大神費心協助,修改後測試還是一樣
小弟之前也有測試切換過SSL加密連線LDAP但是還是失敗......
現在的程式碼如下

<?php
$ldap_host = 'ldaps://192.168.90.211';
$ldap_port = 636;
$ldap_user = 'cn=ldapadmin,dc=black,dc=vhoffice,dc=com'; // LDAP管理員用戶名稱
$ldap_pass = 'Rmbi_6894'; // LDAP管理員密碼

$ldap_conn = ldap_connect($ldap_host, $ldap_port);

if (!$ldap_conn) {
    echo "無法連線到 ldap 服務器\n";
    exit;
}

// 绑定LDAP管理員用户
putenv('LDAPTLS_REQCERT=never');
$ldap_bind = ldap_bind($ldap_conn, $ldap_user, $ldap_pass);

if (!$ldap_bind) {
    echo "LDAP管理員綁定失敗\n";
    exit;
}

echo "成功連接並綁定\n";
?>

錯誤畫面....https://ithelp.ithome.com.tw/upload/images/20240304/20006167w7LdjxaTvM.jpg

Ray iT邦大神 1 級 ‧ 2024-03-04 22:19:06 檢舉

不對....

你不能同時使用 ldaps/636 又要 putenv('LDAPTLS_REQCERT=never');

putenv('LDAPTLS_REQCERT=never'); 這條本身的意義就是叫他不要使用 SSL 了; 結果你上面又寫 636 和 ldaps 要用 SSL, 這兩件事情是互相衝突的

兩個只要選擇一個用就好, 並不是兩個可以同時使用...

  • 寫了 putenv('LDAPTLS_REQCERT=never'); (不用SSL) 就不可用 ldaps/Port 636 (有SSL); 要改用 ldap/389 (沒有SSL)
  • 用了 ldaps/Port 636 (強制用 SSL) 就不可寫 putenv('LDAPTLS_REQCERT=never');(不用SSL)

謝謝Ray大神的指導,不過我剛剛測試兩種方式,錯誤訊息都一樣
不管是拿掉putenv('LDAPTLS_REQCERT=never');純粹用ldaps
或者是只用putenv('LDAPTLS_REQCERT=never');這個不走SSL
都是與上面的錯誤訊息相同....

Ray iT邦大神 1 級 ‧ 2024-03-05 07:08:56 檢舉

好, 我們重新來過...

我剛看了前面的過程, 發現你的錯誤是出在 Line 15 (or 16), 這代表前面的 ldap_connect() 是成功的, 所以你再驗證一下, 看看:有 SSL 和沒有 SSL, 他們的錯誤分別會出現在哪一行?

如果是 ldap_connect 那行出錯, 代表這個連線方法不對, 要用另外一種; 但是如果出錯的是 ldap_bind() 這行, 代表: 前面的連線已經通過了, 這時候就不是 port or SSL 的問題, 是你的帳號密碼問題.

所以請再確認一下出錯的行號? 若是 ldap_bind() 這行的話, 要從你的 username password 去下手查, 而不是連線的參數.

如果把:
$ldap_user = 'cn=ldapadmin,dc=black,dc=vhoffice,dc=com';
換成:
$ldap_user = 'ldapadmin@black.vhoffice.com';
這樣呢?

謝謝Ray大神耐心協助,我各做了兩個方式對照如下,但是我覺得錯誤都是一樣的,應該與帳號方式無關,而密碼的部分我有再三確認過,因為現在登入就是使用這個帳號登入Win10,所以應該也不是密碼錯誤。
1.使用LDAPS方式,採用不同的帳號方式

<?php
$ldap_host = 'ldaps://192.168.90.211';
$ldap_port = 636;
$ldap_user = 'cn=ldapadmin,dc=black,dc=vhoffice,dc=com'; // LDAP管理員用戶名稱
$ldap_pass = 'Rmbi_6894'; // LDAP管理員密碼

$ldap_conn = ldap_connect($ldap_host, $ldap_port);

if (!$ldap_conn) {
    echo "無法連線到 ldap 服務器\n";
    exit;
}

// 绑定LDAP管理員用户
// putenv('LDAPTLS_REQCERT=never');
$ldap_bind = ldap_bind($ldap_conn, $ldap_user, $ldap_pass);

if (!$ldap_bind) {
    echo "LDAP管理員綁定失敗\n";
    exit;
}

echo "成功連接並綁定\n";
?>

https://ithelp.ithome.com.tw/upload/images/20240305/20006167mqj8uHy6xM.jpg

<?php
$ldap_host = 'ldaps://192.168.90.211';
$ldap_port = 636;
$ldap_user = 'ldapadmin@black.vhoffice.com'; // LDAP管理員用戶名稱
$ldap_pass = 'Rmbi_6894'; // LDAP管理員密碼

$ldap_conn = ldap_connect($ldap_host, $ldap_port);

if (!$ldap_conn) {
    echo "無法連線到 ldap 服務器\n";
    exit;
}

// 绑定LDAP管理員用户
// putenv('LDAPTLS_REQCERT=never');
$ldap_bind = ldap_bind($ldap_conn, $ldap_user, $ldap_pass);

if (!$ldap_bind) {
    echo "LDAP管理員綁定失敗\n";
    exit;
}

echo "成功連接並綁定\n";
?>

https://ithelp.ithome.com.tw/upload/images/20240305/20006167GutZo1ZXh6.jpg
2.使用LDAP方式,採用不同的帳號方式

<?php
$ldap_host = 'ldap://192.168.90.211';
$ldap_port = 389;
$ldap_user = 'cn=ldapadmin,dc=black,dc=vhoffice,dc=com'; // LDAP管理員用戶名稱
$ldap_pass = 'Rmbi_6894'; // LDAP管理員密碼

$ldap_conn = ldap_connect($ldap_host, $ldap_port);

if (!$ldap_conn) {
    echo "無法連線到 ldap 服務器\n";
    exit;
}

// 绑定LDAP管理員用户
putenv('LDAPTLS_REQCERT=never');
$ldap_bind = ldap_bind($ldap_conn, $ldap_user, $ldap_pass);

if (!$ldap_bind) {
    echo "LDAP管理員綁定失敗\n";
    exit;
}

echo "成功連接並綁定\n";
?>

https://ithelp.ithome.com.tw/upload/images/20240305/200061673oYPOLPiUX.jpg

<?php
$ldap_host = 'ldap://192.168.90.211';
$ldap_port = 389;
$ldap_user = 'ldapadmin@black.vhoffice.com'; // LDAP管理員用戶名稱
$ldap_pass = 'Rmbi_6894'; // LDAP管理員密碼

$ldap_conn = ldap_connect($ldap_host, $ldap_port);

if (!$ldap_conn) {
    echo "無法連線到 ldap 服務器\n";
    exit;
}

// 绑定LDAP管理員用户
putenv('LDAPTLS_REQCERT=never');
$ldap_bind = ldap_bind($ldap_conn, $ldap_user, $ldap_pass);

if (!$ldap_bind) {
    echo "LDAP管理員綁定失敗\n";
    exit;
}

echo "成功連接並綁定\n";
?>

https://ithelp.ithome.com.tw/upload/images/20240305/20006167VhXQVIqwEa.jpg

Ray iT邦大神 1 級 ‧ 2024-03-05 23:32:52 檢舉

關鍵還是在 Line 16 的 bind, 不過我目前看不出他哪裡有問題...

其實這也是我的疑問,目前我最大的懷疑就是XAMPP的版本問題
不知道Ray大神有用什麼版本是正常的嗎?

Ray iT邦大神 1 級 ‧ 2024-03-06 12:30:33 檢舉

PHP8, 不過我沒聽說有其他版本的 PHP 出過類似的 ldap 問題.

明白.....看起來無解了

抱歉,補問Ray大神
請問您的開發環境有另外安裝OpenLDAP這個套件嗎?還是純粹用XAMPP的開發環境?

Ray iT邦大神 1 級 ‧ 2024-03-06 21:37:33 檢舉

我在 Linux 環境去使用 AD/LDAP, 沒有用 XAMPP, 根據這份文件:
https://reintech.io/blog/introduction-php-ldap-library-directory-access
你只需要有 PHP Extension 就夠了, OpenLDAP 只是用來建立一個模擬用的 LDAP Server 提供測試而已, 如果已經有任何一台可以正常工作的 LDAP Server, 就不需要使用 OpenLDAP.

謝謝Ray大神的回覆。
小弟這邊後來乾脆直接重新建構了一個測試環境Win Server 2022 AD+Win10,在這個測試環境內下述程式是可以正常運作的,但是我挪至正式環境內卻顯示帳號密碼失敗........不知道大神有遇過這個問題嗎?

<?php
// LDAP 伺服器設定
$ldapServer = 'ldap://php.vhoffice.com';
$ldapBaseDn = 'php.vhoffice.com'; // 根 DN

// 如果有提交登入表單
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    // 獲取使用者提交的帳號和密碼
    $username = $_POST['username'];
    $password = $_POST['password'];

    // 連接到 LDAP 伺服器
    $ldapConn = ldap_connect($ldapServer);

    if ($ldapConn) {
        // 進行 LDAP 綁定
        $ldapBind = @ldap_bind($ldapConn, "$username@$ldapBaseDn", $password);

        if ($ldapBind) {
            // 驗證成功
			if (!empty($_SERVER["HTTP_CLIENT_IP"])){
				$ip = $_SERVER["HTTP_CLIENT_IP"];
			}elseif(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])){
				$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
			}else{
				$ip = $_SERVER["REMOTE_ADDR"];
			}
            echo "帳號驗證登入成功!".'<BR>';
			echo '驗證使用者帳號為 '.$username.'<BR>';
			echo '使用者來源IP Address為 '.$ip.'<BR>';
        } else {
            // 驗證失敗
            echo "帳號或密碼錯誤。";
        }

        // 關閉 LDAP 連接
        ldap_unbind($ldapConn);
    } else {
        // 連接失敗
        echo "無法連接到 LDAP 伺服器。";
    }
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>LDAP 帳號驗證</title>
</head>
<body>
    <h2>LDAP 帳號驗證</h2>
    <form method="post" action="">
        <label for="username">帳號:</label><br>
        <input type="text" id="username" name="username" required><br>
        <label for="password">密碼:</label><br>
        <input type="password" id="password" name="password" required><br><br>
        <input type="submit" value="登入">
    </form>
</body>
</html>

感謝Ray大神,已解決。

我要發表回答

立即登入回答