系統環境: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);
你有沒有先用 ldp 工具, 去驗證你的 AD 已經開放 LDAP Server?
https://www.cisco.com/c/zh_tw/support/docs/unified-communications/jabber/212109-How-to-Use-LDP-EXE-to-Search-LDAP-Server.html
抱歉,漏了描述
你的 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大神的誤解,小弟說明一下
那你的 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";
?>
錯誤畫面如下圖
後面的錯誤寫:
...Stronger authentication required...
此錯誤代表:
AD Server 要求你必須透過 SSL 加密才能進行帳號驗證.
這有兩種解法:
$ldap_host = 'ldaps://192.168.90.211';
$ldap_port = 636;
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";
?>
錯誤畫面....
不對....
你不能同時使用 ldaps/636 又要 putenv('LDAPTLS_REQCERT=never');
putenv('LDAPTLS_REQCERT=never'); 這條本身的意義就是叫他不要使用 SSL 了; 結果你上面又寫 636 和 ldaps 要用 SSL, 這兩件事情是互相衝突的
兩個只要選擇一個用就好, 並不是兩個可以同時使用...
謝謝Ray大神的指導,不過我剛剛測試兩種方式,錯誤訊息都一樣
不管是拿掉putenv('LDAPTLS_REQCERT=never');純粹用ldaps
或者是只用putenv('LDAPTLS_REQCERT=never');這個不走SSL
都是與上面的錯誤訊息相同....
好, 我們重新來過...
我剛看了前面的過程, 發現你的錯誤是出在 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";
?>
<?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";
?>
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";
?>
<?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";
?>
關鍵還是在 Line 16 的 bind, 不過我目前看不出他哪裡有問題...
其實這也是我的疑問,目前我最大的懷疑就是XAMPP的版本問題
不知道Ray大神有用什麼版本是正常的嗎?
PHP8, 不過我沒聽說有其他版本的 PHP 出過類似的 ldap 問題.
明白.....看起來無解了
抱歉,補問Ray大神
請問您的開發環境有另外安裝OpenLDAP這個套件嗎?還是純粹用XAMPP的開發環境?
我在 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大神,已解決。