無密碼 LDAP 登入並使用 PHP 中的 Kerberos 票證取得使用者資訊
P粉071743732
P粉071743732 2024-03-26 10:40:55
0
1
453

我正在嘗試使用 FreeIPA/Kerberos 在我們公司的一些 Intranet 網站上實現 SSO。但關於這個主題的資訊非常少。

我的測試網路中運行著三台機器:

  1. Centos 8 Stream 上的 FreeIPA v4.9.8 伺服器
  2. Debian 11 上的網路伺服器(Apache v2.4.53、PHP v7.4.28)
  3. 帶有 Kinit 和 Firefox 的 Xubuntu 22.04 用戶端

Kinit、Unix 登入和 Apache Kerberos Auth 工作。用戶端系統上的Firefox瀏覽器無需密碼即可登入FreeIPA WebConfig(使用Kerberos Ticket)。我現在想將此功能轉移到我們的內部網路頁面。到目前為止,這些頁面的登入都是基於傳統的 LDAP 登入。透過登入腳本進行細微調整,使用者現在可以登入新的 FreeIPA 伺服器。但是,他仍然需要密碼,但由於 Kerberos 票證,實際上不再需要密碼。

問題是,無密碼登入是什麼樣的?

登入腳本的功能片段:

<?php
$username = $_SERVER['PHP_AUTH_USER'];
$password = 'password';

$ldap_rdn  = 'uid='.$username.',cn=users,cn=accounts,dc=exampletest,dc=de';
$ldap_server = ldap_connect('ldap://ipa.exampletest.de:389');

ldap_set_option($ldap_server, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap_server, LDAP_OPT_REFERRALS, 0);

if ($ldap_server) {
  $ldap_bind = @ldap_bind($ldap_server, $ldap_rdn, $password);
  if ($ldap_bind) {
    $search = array("uid","givenname","sn","mail","uidnumber","gidnumber");
    $result = ldap_search($ldap_server, $ldap_rdn, "mail=$username*", $search);
    $info = ldap_get_entries($ldap_server, $result);

    print_r($info);
  }
}
?>

現在我有兩個想法:

  1. 我可以使用ldap_sasl_bind() 而不是ldap_bind(),但函數沒有記錄在php.net (https://www.php.net/manual/en/function.ldap-sasl-bind.php) 上。如果有人知道如何使用此功能,我將不勝感激。
  2. 如果我能以某種方式在沒有密碼的情況下運行 ldap_search() 來獲取使用者資訊(全名、電子郵件等),我也會很高興。

提前非常感謝。

編輯:

Web 伺服器 VM 和客戶端 VM 皆透過「ipa-client-install」初始化。另外,Web伺服器已經註冊了apache服務(ipa service-add HTTP/ebook.exampletest.de)。

apache 設定也反映了這一點:

<Directory /var/www/ebook/>
        AuthType                GSSAPI
        AuthName                "eBook Login"
        GssapiCredStore         keytab:/etc/apache2/http.keytab
        GssapiAllowedMech       krb5
        GssapiBasicAuthMech     krb5
        GssapiImpersonate       On
        GssapiDelegCcacheDir    /run/apache2/clientcaches
        GssapiLocalName         On
        
        # for production set to on:
        GssapiSSLonly           Off
        GssapiNegotiateOnce     Off
        
        GssapiUseSessions       On
        Session                 On
        SessionCookieName       gssapi_session path=/private;httponly;secure;
        Require                 valid-user
    </Directory>
正如我已經提到的,用戶身份驗證似乎是這樣工作的(client(自己的票) > web 服務(自己的票) > ipa server )。否則 apache 伺服器不會傳回我的 ldap/kerberos 使用者名稱。或者我在這裡遺漏了一些重要的東西?有其他方法可以強制執行這種身份驗證嗎?

輸出:<?php print_r($_SERVER) ?>(已截取)

[GSS_MECH] => Negotiate/krb5
[GSS_NAME] => test@EXAMPLETEST.DE
[REMOTE_USER] => test
[AUTH_TYPE] => Negotiate
[PHP_AUTH_USER] => test

P粉071743732
P粉071743732

全部回覆(1)
P粉614840363

確保您的 Web 伺服器具有正確 Kerberos 票證。

通常,Kerberos 驗證僅傳輸僅對該伺服器有效的票證,而不是一攬子「所有」票證。當用戶端對您的 web 應用程式進行身份驗證時,您獲得的只是 HTTP/webapp.example.tld 的票證,而且您無法真正使用它來代表使用者存取 LDAP。

如果您需要代表使用者存取 LDAP,則有以下幾種選擇:

  • 網路應用程式可以擁有自己的 LDAP 目錄憑證。這可能是最簡單的方法。 Web 應用程式可以使用標準密碼綁定,也可以使用從金鑰表取得的自己的票證進行 Kerberos (SASL) 綁定。

    • LDAP 還支援“模擬”,即Web 應用程式將使用自己的憑證進行身份驗證,但指定一個“授權ID”(authzid) 來確定您將獲得哪個帳戶的權限。

      例如,如果您以「webapp」身份進行驗證,但指定了authzid「myuser」(並且如果LDAP 伺服器允許),那麼您將獲得「myuser」通常所擁有的權限有– 而不是「webapp」的那些。

  • Web 應用程式的 HTTP 協商 (SPNEGO) 驗證可以啟用「委託」。委派確實將主krbtgt票證傳輸到Web伺服器,然後伺服器會將其放入臨時票證快取中並可供您的Web應用程式環境使用。

    但是,委託有一些問題:

    1. 這會使每個HTTP 請求變慢,因為客戶端必須要求帶有「轉發」標誌的新krbtgt 票證(除非Web 伺服器可以使用例如cookie 來避免請求協商身份驗證)用於進一步的請求,例如帶有“會話”模式的mod_auth_gssapi)。

    2. 它要求Web 應用程式高度可信,因為它將為每個存取它的使用者(包括管理員)儲存通配符票證- 即使Web 應用程式本身被信任不會濫用它們,它們仍然可能被竊取伺服器。

    3. 大多數使用 Kerberos 的 API(包括 ldap_sasl_bind())都期望 KRB5CCNAME 環境變數指向票證快取。但環境變數是進程範圍的,因此只要 PHP 重複使用相同進程,它們就可能會在不相關的請求中洩漏(或者更糟的是,如果您使用 mod_php 在 Apache 進程內執行 web 應用程式)。

    在 AD 中,這具體稱為“無約束委派”,因為 AD 引入了其他變體。

  • 網路應用程式可以使用S4U2Proxy 又稱為「約束委派」來代表使用者建立票證,以取得某些有限的服務集(例如,FreeIPA 可以將其限制為僅存取ldap/foo.example.com)。

    這有點複雜(PHP 沒有這方面的 API - 您可能需要使用正確的標誌產生 kinit),並且仍然存在與 KRB5CCNAME 跨請求洩漏相同的潛在問題。

對於常規 Kerberos 驗證,用法如下所示:

ldap_sasl_bind($conn, null, null, "GSSAPI");

僅此而已。 GSSAPI SASL 機制期望環境已經具有可用的 Kerberos 票證(例如透過 $KRB5CCNAME 或透過 gss-proxy),並且它將使用在那裡找到的任何票證進行身份驗證。

如果您想要使用模擬(假設在 LDAP 伺服器中設定),則必須指定 authz_id:

ldap_sasl_bind($conn, null, null, "GSSAPI", null, null, $theuser);

大多數 ldap_*() PHP 函數都是 C libldap 函式庫的直接包裝器,因此其文件可作為部分參考。

看來您的範例已經指定了使用者的確切DN,因此似乎不需要透過mail 進行額外過濾- 只需在讀取郵件時使用objectClass=*特定的DN。另外,當您想要讀取特定 DN 時,請使用 ldap_read() 進行「基本」搜尋而不是子樹搜尋。

不,事情不是這樣的。您的使用者名稱(即用戶端 Kerberos 主體)儲存在用戶端票證中,因此 Web 伺服器在解密票證後立即知道它,而無需與 IPA 對話。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!