Autor Zpráva
ALLSSA
Profil
Dobrý den,
chtěl bych se zeptat na vaše zkušenosti ohledně Active Directory přes NTLM. Potřeboval bych zprovoznit přihlašování na webové stránce (Nette, PHP 5.6, Win) kdy ideálně po vyplnění domény do adresního řádku dojde rovnou k přihlášení a uživatel je přesměrován rovnou na úvodní stránku. V současné chvíli zaostává pouze samotné přihlášení a po několika hodinách na googlu jsem spíš víc zmatený. Většinou se radí LDAP, ale nad tím nemám kontrolu. Otázky jsou následující:

1) Je možné rozchodit přihlašování (viz. výše) přes NTLM?
2) Jak by to teoreticky mělo probíhat?
3) Co bych měl případně nastudovat za materiály? (či klíčová slova k vyhledávání)

Děkuji za rady.
Enko
Profil
Ahoj,
přesně tyto technologie používám pro své intranetové aplikace. Záleží co od toho všechno očekáváš a požaduješ.
Nejjednodušší je používání NTLM, kdy si pomocí například tohoto skriptu zjistíš jméno přihlášeného uživatele. Problém je, že to jde provést pouze v IE, ale není to úplně spolehlivé. Uživatel si může v nastavení zabezpečí odškrtnout nepoužívat NTLM. V jiných prohlížečích nejde NTLM realizovat (nebo nešlo, když jsem to kdysi před lety řešil). Tzn, pokud máš možnost vynutit používání pouze IE, tak toto je zajímavá varianta a pro uživatele nejjednodušší, protože se nemusí znovu přihlašovat do tvé aplikace pod doménovým účtem.
Pokud chceš mít ale jistotu ověření, že se skutečně jedná o uživatele a skutečně ho ověřit vůči AD, zda například je v konkrétní organizační struktuře, zda není zakázaný jeho účet, atd... Tak musíš použít LDAP, kteréje velmi jednoduché. Níže přikládám skript na ověření uživatele v AD přes LDAP za pomocí jeho doménového loginu a hesla.

<?php
//funkce na overeni uzivatelskeho prihlase do AD
function authUserAD($username, $password, $DomainName="nazevdomeny.ad", $ldap_server="ldap://domaincontroller001.nazevdomeny.ad") {
  $auth_user = $username."@".$DomainName;
  if($connect = ldap_connect($ldap_server)){
    ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
    ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
    if(ldap_bind($connect, $auth_user, $password)) {
      ldap_close($connect);
      return(true);
    }
  }
  ldap_close($connect);
  return(false);
}

//funkce na vycisteni vstupu do LDAP
/**
 * function ldap_escape
 * @author Chris Wright
 * @version 2.0
 * @param string $subject The subject string
 * @param bool $dn Treat subject as a DN if TRUE
 * @param string|array $ignore Set of characters to leave untouched
 * @return string The escaped string
 */
function ldap_escape ($subject, $dn = TRUE, $ignore = NULL) {

    // The base array of characters to escape
    // Flip to keys for easy use of unset()
    $search = array_flip($dn ? array('\\', ',', '=', '+', '<', '>', ';', '"', '#') : array('\\', '*', '(', ')', "\x00"));

    // Process characters to ignore
    if (is_array($ignore)) {
        $ignore = array_values($ignore);
    }
    for ($char = 0; isset($ignore[$char]); $char++) {
        unset($search[$ignore[$char]]);
    }

    // Flip $search back to values and build $replace array
    $search = array_keys($search);
    $replace = array();
    foreach ($search as $char) {
        $replace[] = sprintf('\\%02x', ord($char));
    }

    // Do the main replacement
    $result = str_replace($search, $replace, $subject);

    // Encode leading/trailing spaces in DN values
    if ($dn) {
        if ($result[0] == ' ') {
            $result = '\\20'.substr($result, 1);
        }
        if ($result[strlen($result) - 1] == ' ') {
            $result = substr($result, 0, -1).'\\20';
        }
    }

    return $result;
}

//pouziti

//osetreni vstupu proti LDAP Injection a odstraneni mezer
$username = ldap_escape(trim($_POST["username"]));
$password = ldap_escape(trim($_POST["password"]));

if(authUserAD($username, $password)){
  //overeni vuci AD je OK, zde si nastavis nejake hodnoty napr SESSIOn o prihlaseni a presmerujes na pozadovamnou stranku po prihlaseni
}
else{
  echo "<p class=\"error\"><strong>Zadal jsi nesprávné přihlašovací údaje nebo je tvůj účet uzamčen.</strong> Zkus to znovu.</p>";
}

?>



Pokud potřebuješ více informací, dej vědět. S LDAP už nějaký čas pracuji a je to velmi jednoduché. Funguje to prakticky stejně jako pokládání dotazů do databáze, jen je jiná syntaxe dotazů.


nebo mě ještě napadlo používat ADFS, ale s tím nemám žádnou konkrétní zkušenost. Znamenalo by to ale mít aktivní ADFS u tebe v infrastruktuře a pak už na to použít nějakou knihovnu, která to bude umět. Jen namátkou jsem něco vygooglil.
ALLSSA
Profil
Enko:
Dobrý den, děkuji že jste odpověděl a omlouvám se, že reaguji s takovým zpožděním, ale vzhledem k tomu, že se mi to nedařilo zprovoznit, zaměřil jsem se na jiné úkoly a vracím se k tomu nyní. A zároveň až nyní jsem si všiml, že mi na můj dotaz někdo odpověděl. Bylo by možné se kontaktovat e-mailem a výsledek bych vložil sem do diskuze, pro další uživatele? Pokud ne, je jistě možné pokračovat zde na fóru.

Moderátor juriad: Odmazána reakce na smazaný příspěvek.
Enko
Profil
ALLSSA:
Klidně mě kontaktuj emailem benda.tomas@gmail.com. V celé této problematice pracuji prakticky denně. Pokud bude zájem, můžu sem hodit pár příkladů, když mi řekneš, co přesně chceš. Jsem ale pro, abychom pak naházeli výsledek i sem. To pro případ, že by to někdo hledal v budoucnu :-)


ALLSSA:
A můžeme si tykat :)
Joker
Profil
ALLSSA, Enko:

Ale můžete to řešit i tady, pro někoho jiného by mohlo být zajímavé i řešení dílčích problémů, na které narazíte.
ALLSSA
Profil
Ahoj, tak se mi to podařilo vyřešit ještě před řešením dílčích problémů.

Podařilo se mi najít dva způsoby, jak pomocí ntlm přihlásit na web.

1) Toto je způsob, který jsem našel sám, ale nebyl jsem z něj moudrý. Odkaz je zde. Nepřišel jsem přesně na to, co se má vyplnit do funkce ntlm_prompt jako parametry. Bohužel si s tím nevěděli rady ani pracovníci firmy, pro kterou jsem to dělal. Nenašel jsem k tomu API ani nic podobného. Vrací se asoviativní pole s autentifikací. V poli by měly být 4 klíče:
$auth["authenticated"] // TRUE nebo FALSE
$auth["domain"] //string
$auth["workstation"] //string
$auth["user"] //username jako string
Nevím to jistě, ale tato varianta by mohla řešit toto:
Enko:
Pokud chceš mít ale jistotu ověření, že se skutečně jedná o uživatele a skutečně ho ověřit vůči AD, zda například je v konkrétní organizační struktuře, zda není zakázaný jeho účet, atd... Tak musíš použít LDAP, kteréje velmi jednoduché. Níže přikládám skript na ověření uživatele v AD přes LDAP za pomocí jeho doménového loginu a hesla.
Pokud neřeší, rád se přiučím.


2) Způsob, který navrhoval Enko.

Nejjednodušší je používání NTLM, kdy si pomocí například tohoto skriptu zjistíš jméno přihlášeného uživatele.

Ten jsem použil já.

V obou případech musíte použít IE, jinak naskočí pouze autentifikační dialog, přes který se ale uživatel nepřihlásí. Pro vlastní obohacení znalostí, by mě celkem zajímalo, čím se tyto dva způsoby liší.
Enko
Profil
ALLSSA:
1) Toto je způsob, který jsem našel sám, ale nebyl jsem z něj moudrý.
Tento způsob není skutečné ověření vůči doménovému kontroleru. Toto jen vyčte informace o přihlášeném uživateli do Internet Exploreru. Konkrétně uživatele přihlášeného do Windows, název počítače a firemní domény, do které je uživatel přihlášen. To je vše. Tyto informace by měly být použity jen jako informační, protože zde nedochází ke skutečnému ověření, vůči doménovému řadiči, zda je uživatel povolený, zda má platný účet, atd... Tento samý skript používám jen pro zjištění informací o přihlášeném uživateli nebo do aplikací, kde není nutné doménové přihlášení.
Pokud potřebuješ skutečně ověřit, jestli je uživatel aktivní, má platný účet, je součástí nějaké skupiny, je v konkrétní složce v Active Directory, musíš použít viz #2.
Můžu sem dát nějaké konkrétní příklady, když mi řekneš, co přesně potřebuješ.
ALLSSA
Profil
Já bohužel nemohu ldap použít. Úkol, který jsem dostal byl založen právě na ntlm. Tím pádem za mne je vlákno vyřešené. Moc děkuji za ochotu a osvětlení problematiky. Co se týče zařazení do různých organizačích skupin, mám rozjeté oboustranný export/import důležitých dat, týkajících se uživatelů, takže s tímhle problémem si také poradím. Pokud by uživatele např. zrušili, druhý den už se nepřihlásí, i kdyby měl kartu.
Enko
Profil
ALLSSA:
Super. jen upozorňuji, že jsem se již ze své praxe setkal s tím, že údaje vyčtené z NTLM jdou v IE podvrhnout. Setkal jsem se s případy, kdy ve Windows zůstalo ve Správci pověření špatné přihlašovací jméno, protože ho tam tak uživatel zadal (např při expiraci hesla vyskočilo okno na zadání aktuální pověření pro proxy a uživatel zaškrtnul "Zapamatovat pověření") a toto špatné přihlašovací jméno se pak zobrazovalo v NTLM, tak na toto pozor a webová apliakce, co čte NTLM rázem nefungovala, tak jak měla. Ale to se mi za několik let používání stalo snad jen jednou. Určitě by se ale našly i jiné způsoby.

Vaše odpověď

Mohlo by se hodit

Příspěvky nesouvisející s webem budou odstraněny.

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: