비밀번호 없는 LDAP 로그인 및 PHP에서 Kerberos 티켓을 사용하여 사용자 정보 가져오기
P粉071743732
P粉071743732 2024-03-26 10:40:55
0
1
472

FreeIPA/Kerberos를 사용하여 우리 회사의 일부 인트라넷 사이트에 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 인증이 작동합니다. 클라이언트 시스템의 Firefox 브라우저는 비밀번호 없이(Kerberos 티켓 사용) FreeIPA WebConfig에 로그인할 수 있습니다. 이제 이 기능을 인트라넷 페이지로 옮기고 싶습니다. 지금까지 이러한 페이지에 대한 로그인은 기존 LDAP 로그인을 기반으로 했습니다. 로그인 스크립트를 약간 조정하면 이제 사용자는 새로운 FreeIPA 서버에 로그인할 수 있습니다. 그러나 여전히 비밀번호가 필요하지만 Kerberos 티켓 덕분에 비밀번호는 실제로 더 이상 필요하지 않습니다.

질문은 비밀번호 없는 로그인이 어떤 모습이냐는 것입니다.

로그인 스크립트의 기능 조각:

으아아아

이제 내 생각에는 두 가지가 있습니다.

  1. ldap_bind() 대신 ldap_sasl_bind()를 사용할 수 있지만 해당 함수는 php.net(https://www.php.net/manual/en/function.ldap-sasl-bind.php)에 문서화되어 있지 않습니다. 혹시 이 기능을 사용하는 방법을 아시는 분이 계시다면 감사하겠습니다.
  2. 사용자 정보(이름, 이메일 등)를 얻기 위해 어떻게든 비밀번호 없이 ldap_search()를 실행할 수 있다면 기쁠 것입니다.

미리 감사드립니다.

편집자:

웹 서버 VM과 클라이언트 VM 모두 "ipa-client-install"을 통해 초기화됩니다. 또한 웹 서버에는 Apache 서비스(ipa service-add HTTP/ebook.exampletest.de)가 등록되어 있습니다.

아파치 구성에는 다음 사항도 반영됩니다.

으아아아 아까도 말씀드렸듯이 사용자 인증은 이런 식으로 되는 것 같아요(client(自己的票) > web 服务(自己的票) > ipa server). 그렇지 않으면 Apache 서버가 내 ldap/kerberos 사용자 이름을 반환하지 않습니다. 아니면 여기서 중요한 것을 놓치고 있는 걸까요? 이 인증을 시행하는 다른 방법이 있습니까?

출력: <?php print_r($_SERVER) ?>(가로채기)

<?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);
  }
}
?>

P粉071743732
P粉071743732

모든 응답(1)
P粉614840363

웹 서버에 올바른 Kerberos 티켓이 있는지 확인하세요.

일반적으로 Kerberos 인증은 "모든" 티켓을 전송하는 것이 아니라 해당 서버에만 유효한 티켓만 전송합니다. 클라이언트가 웹 앱에 인증하면 HTTP/webapp.example.tld에 대한 티켓만 얻을 수 있으며 실제로 사용자를 대신하여 LDAP에 액세스하는 데 사용할 수는 없습니다.

사용자를 대신하여 LDAP에 액세스해야 하는 필요한 경우 몇 가지 옵션이 있습니다.

  • 웹 애플리케이션은 자체 LDAP 디렉터리 자격 증명을 가질 수 있습니다. 아마도 이것이 가장 쉬운 방법일 것입니다. 웹 애플리케이션은 키탭에서 얻은 자체 티켓을 사용하여 표준 비밀번호 바인딩 또는 Kerberos(SASL) 바인딩을 사용할 수 있습니다.

    • LDAP는 웹 애플리케이션이 자체 자격 증명을 사용하여 인증하는 "가장"도 지원하지만 또한 "인증 ID"(authzid)를 지정하여 액세스 권한을 부여받을 계정을 결정합니다.

      예를 들어, "webapp"으로 인증했지만 authzid "myuser"를 지정하는 경우(그리고 LDAP 서버가 이를 허용하는 경우 ) "webapp"이 아닌 "myuser"가 일반적으로 갖는 권한을 얻게 됩니다. .

  • 웹 애플리케이션에 대한 HTTP 협상(SPNEGO) 인증은 "위임"을 활성화할 수 있습니다. 위임 은 마스터 티켓을 웹 서버로 krbtgt 전송한 다음 이를 임시 티켓 캐시에 저장하고 웹 응용 프로그램 환경에서 사용할 수 있도록 합니다.

    그러나 위임에는 몇 가지 문제가 있습니다.

    1. 추가 요청을 위해 클라이언트가 "전달" 플래그를 사용하여 새 krbtgt 티켓을 요청해야 하기 때문에(예: 협상된 인증 요청을 피하기 위해 쿠키를 사용할 수 없는 경우) 모든 HTTP 요청 속도가 느려집니다. "세션" 모드).

    2. 웹 애플리케이션에 액세스하는 모든 사용자(관리자 포함)에 대해 와일드카드 티켓을 저장하므로 웹 애플리케이션의 신뢰도가 높아야 합니다. 웹 애플리케이션 자체가 이를 남용하지 않을 것으로 신뢰되더라도 여전히 서버에 의해 손상될 수 있습니다.

    3. Kerberos(ldap_sasl_bind() 포함)를 사용하는 대부분의 API는 KRB5CCNAME 환경 변수가 티켓 캐시를 가리킬 것으로 예상합니다. 그러나 환경 변수는 프로세스 범위이므로 PHP가 동일한 프로세스를 재사용할 때마다(또는 더 나쁜 경우 mod_php를 사용하여 Apache 프로세스 내에서 웹 애플리케이션을 실행하는 경우) 관련 없는 요청에서 누출될 수 있습니다.

    AD에서는 AD가 다른 변형을 도입했기 때문에 이를 구체적으로 "무제한 위임"이라고 합니다.

  • 웹 애플리케이션은 S4U2Proxy(일명 "제한된 위임")를 사용하여 사용자를 대신하여 특정 제한된 서비스 세트에 대한 티켓을 생성할 수 있습니다(예: FreeIPA는 액세스만 ldap/foo.example.com하도록 제한할 수 있습니다).

    이것은 약간 복잡하며(PHP에는 이에 대한 API가 없습니다. 올바른 플래그를 사용하여 생성해야 할 수도 있습니다 kinit) 여전히 KRB5CCNAME 교차 요청 누출과 동일한 잠재적인 문제가 있습니다.

일반 Kerberos 인증의 경우 사용법은 다음과 같습니다.

으아아아

그게 다예요. GSSAPI SASL 메커니즘은 환경에 이미 사용 가능한 Kerberos 티켓이 있을 것으로 예상하고(예: $KRB5CCNAME 또는 gss-proxy를 통해) 거기에서 발견된 티켓을 사용하여 인증합니다.

가장을 사용하려면(LDAP 서버에 설정되어 있다고 가정) authz_id를 지정해야 합니다:

으아아아

대부분의 ldap_*() PHP 함수는 C libldap 라이브러리의 직접 래퍼이므로 해당 문서를 부분 참조로 사용할 수 있습니다.

귀하의 예에서는 이미 사용자의 정확한 DN을 지정하고 있으므로 mail 进行额外过滤 - 只需在读取邮件时使用 objectClass=*특정 DN을 전달할 필요는 없는 것 같습니다. 또한 특정 DN을 읽으려면 하위 트리 검색보다는 "기본" 검색을 위해 ldap_read()를 사용하세요.

아니요, 그런 일은 일어나지 않았습니다. 귀하의 사용자 이름(예: 클라이언트 Kerberos 주체)은 클라이언트 티켓에 저장되므로 웹 서버는 IPA와 통신할 필요 없이 티켓을 해독한 후 즉시 이를 알 수 있습니다.

최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿