Přihlašování uživatelů
Školení, která pořádám
Pokud mají mít na některé stránky přístup jen vybraní uživatelé, musí se nejprve nějak přihlásit. Způsobu ověření jejich jména a hesla je jako obvykle více.
PHP podporuje standardní HTTP autentizaci prostřednictvím proměnných $_SERVER['PHP_AUTH_USER'] a $_SERVER['PHP_AUTH_PW'].
<?php
$row = mysql_fetch_assoc(mysql_query("SELECT * FROM uzivatele WHERE login = '" . mysql_real_escape_string($_SERVER['PHP_AUTH_USER']) . "' AND heslo = '" . md5($_SERVER['PHP_AUTH_PW']) . "'"));
if (!$row) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Basic realm="Název aplikace"');
page_header("Přihlášení");
echo "<p>Pro přístup na tuto stránku se musíte přihlásit.</p>\n";
page_footer();
exit;
}
?>
Výhoda tohoto přístupu spočívá v relativně nižší pracnosti a také v tom, že uživatel se může přihlásit standardním způsobem přes http://login:heslo@www.example.com
, byť se to asi málokdy použije – v IE 6 v XP SP2 byl tento způsob zápisu adresy z bezpečnostních důvodu navíc zakázán. Někdo může za výhodu považovat také to, že se pro přihlášení zobrazí standardní dialog prohlížeče, pro jiného to ale bude spíše nevýhoda. Jasná nevýhoda je ta, že přihlašovací data se přenášejí při každém stažení stránky nešifrovaně a navíc ve standardizované podobě, takže je pro různé sniffery jednodušší je získat. Problém je také s odhlášením – např. v Mozille stačí poslat hlavičku 401 (na uživatele ale potom místo informace o odhlášení vybafne přihlašovací dialog), v Internet Exploreru bylo nutné otevřít adresu s neplatným uživatelem (např. http://neexistuje@www.example.com
), kvůli výše uvedenému omezení ale není možné už ani to. Poslední zádrhel se skrývá v tom, že pokud nemáte pod kontrolou všechny skripty na celé doméně (to je např. případ domácích stránek studentů a učitelů na školách), může záškodník použít stejný realm a tím potenciálně získat přihlašovací údaje uživatele (pokud ho přiměje po přihlášení k aplikaci navštívit své stránky). To je také důvod, proč se při zapnutém safe_mode do realmu doplňuje UID vlastníka skriptu. To pochopitelně vzhled standardního přihlašovacího dialogu poněkud nabourává.
Ve většině případů je proto asi lepší si přihlašování zařídit sám. Informace o přihlášenosti uživatele se dá ukládat např. do session.
<?php
if (isset($_POST["auth_login"])) {
if (mysql_result(mysql_query("SELECT COUNT(*) FROM uzivatele WHERE login = '" . mysql_real_escape_string($_POST["auth_login"]) . "' AND heslo = '" . md5($_POST["auth_heslo"]) . "'"), 0)) {
session_regenerate_id(); // ochrana před Session Fixation
$_SESSION["logged"] = true;
}
}
if (!isset($_SESSION["logged"])) {
page_header("Přihlášení");
if (isset($_POST["auth_login"])) {
echo "<p>Neplatné přihlašovací údaje.</p>\n";
}
echo "<form action='' method='post'>\n";
echo "<p>Login: <input name='auth_login' maxlength='30' /></p>\n";
echo "<p>Heslo: <input type='password' name='auth_heslo' /></p>\n";
echo "<p><input type='submit' value='Přihlásit' /></p>\n";
echo "</form>\n";
page_footer();
exit;
}
?>
Tento způsob je o něco pracnější, výhoda je ta, že máme vše pod kontrolou. Pozor je ale potřeba dát na zabezpečení session proměnných. Odhlášení je triviální, stačí provést unset($_SESSION["logged"])
.
Pokud používáte protokol HTTPS, můžete také využít přihlašování pomocí klientských certifikátů, ale obzvláště s jejich generováním je o něco více práce. Bezpečnost je každopádně s přihlašováním pomocí hesla nesrovnatelná.
Zbývá popsat, jak to slepit dohromady. Osobně umísťuji kód zajišťující přihlášení do souboru auth.inc.php
a do všech souborů vyžadujících přihlášení tento soubor vložím. Výhoda je velká – můžu uživatelům nabídnout jakýkoliv odkaz (např. v e-mailu) a pokud se na stránku podívají nepřihlášení, rovnou se jim zobrazí přihlašovací dialog, po jehož vyplnění se stránka zobrazí. Někdo preferuje v případě nepřihlášení přesměrování na přihlašovací dialog hlavičkou Location. Pokud se přihlašovacímu dialogu předá adresa stránky, na kterou uživatel přišel, dá se dosáhnout stejné funkčnosti, jen je s tím o něco víc práce. Nezbytně nutné je provést po přesměrování exit, protože jinak se celá stránka, která by měla být dostupná jen pro přihlášené uživatele, bez okolků pošle (v prohlížeči se sice nestihne zobrazit, útočník se k ní ale může snadno dostat).
Viz také: Bezpečné přihlašování uživatelů.
Diskuse
halogan:
Mam otazku: Mam php soubor v UTF a i kdyz poslu hlavicku o tom, ze je v UTF, tak se sice error napise se spravnou diakritikou, ale Basic realm (Nazev aplikace) nikoliv, kde delam chybu?
Svedl bych to na prohlížeč, ale IE 6, FF 1 i Opera 8 se chovají stejně. Hlavička Content-Type se k realm pravděpodobně nevztahuje a prohlížeč zobrazuje realm ve svém přirozeném kódování.
Nezbývá zdá se nic jiného než používat pouze znaky bez diakritiky.
halogan:
Asi ano :/ Zkousel jsem kvuli tomu Operu 8, FF 1.0.6 i Konqueror a nic...
POZOR:
Tka to ti nevodpovím na takovou pakárnu - přečti si to znova!!!!!!!!!!!!!!!!!!§§
Blizz:
Bude to asi tim, ze moza mas v hlavicce nastavene utf-8, ale soubor neni v tom kodovani ulozeny.. stahni si program pspad, otevri v nem ten soubor, klikni nahore v liste na Format, potom vyber utf-8 a uloz ho.. melo by fungovat
Kalda:
Mám pár poznámek k HTTP autentifikaci:
1) http://login:heslo@www.example.com je zakázáno ve Windows XP sice až od SP2, ale pokud uživatelé provádí pravidelné aktualizace Windows, tak to bylo zakázáno již mnohem dříve (lze opětovně povolit úpravou registrů).
2) tenhle způsob (poslání hlavičky 401) funguje pouze pokud běží PHP jako modul serveru, pokud běží jako CGI, tak to nefunguje (pokud to nebylo doplněno)
3) přenášení dat je nešifrované pouze při použití metody basic. Existuje metoda digest, která přenáší data v šifrované podobě (MD5). Její implementace je v PHP trošku komplikovanější -
http://www.xiven.com/sourcecode/digestauthentication
salko:
3) přenášení dat je nešifrované pouze při použití metody basic. Existuje metoda digest, která přenáší data v šifrované podobě (MD5). Její implementace je v PHP trošku komplikovanější -
http://www.xiven.com/sourcecode/digestauthenticationTo sice existuje, ale velmi dlhu dobu nefungovala pod IE, neviem, ci sa tento stav zmenil. DIGEST fungoval v Mozille, FF, Opere a dalsimi prehladacmi, ale rozhodne nie v IE.
Kalda:
Jsem čekal, že se někdo takový ozve ;)
Digest metodu podporuje i IE, minimálně od verze 5.0. Ale jak už je u IE zvykem, opět nedodržuje daný standard.
Pokud metodu digest zasílá IIS, je vše v pořádku.
Dnes je již známá podstata problému a v PHP skriptu, na který jsem odkazoval, je použit "hack", který danou chybu odstraňuje (nestudoval jsem, v čem to spočívá, pouze jsem to viděl v komentáři).
Pokud používáte Apache a mod_digest, tak si přečtěte následující:
http://httpd.apache.org/docs/2.0/mod/mod_auth_digest.html#msie
salko:
Dakujem za vysvetlenie, ja si matne spominam, ze digest mal problem v IE prave pri POST metode, GET fungovala uplne normalne. Ale v tom case, ked som to potreboval (-1.5 roka), tak mi viaceri administratori nevedeli pomoct, iba mi vysvetlili, ze IE+POST+DIGEST je nefunkcne riesenie. A kedze ja som iba programator, tak som sa s tym musel zmierit.
Zdeněk Merta:
Uff, ten skript vypadá dost drsně. Ne že bych někdy studoval metodu Digest, ale vypadá to dost komplikovaně :-D
Kalda:
Vypadá to sice drsně, ale je to lepší, než nefunkční řešení, které je na
http://www.php.net/manual/en/features.http-auth.php (na což odkazuje Jakub).
Mimochodem doplním ještě sám sebe - na tomto odkazu je i popisovaný problém s CGI a IIS, který je vyřešen od PHP verze 4.3.3.
Kolo:
Kdyz tam vidim to unset. Kde je vhodne ho pouzivat a kde ne. Protoze ja unset pouzivam skoro vsude, kdyz tu promennou nepotrebuji. Treba:
$query = "SQL prikaz";
$result = SQL_Query ($query);
unset ($query)
if ($result) { neco}
else { chyba}
unset $result;
Je to zbytecne ci nikoliv? Nevim, ja radsi vse nicim nez se zabyvat pripadnyma memory leakama.
Jakub Vrána :
PHP zabranou paměť automaticky uvolní po dokončení požadavku. Takže volat unset() buď chvíli před koncem skriptu, nebo na zanedbatelně veliká data, je v podstatě zbytečné.
Jakub Vrána :
Místo unset($result) je rozhodně lepší volat mysql_free_result($result), případně oboje. unset($result) uvolní z paměti proměnnou typu resource (tedy pár bajtů), kdyžto mysql_free_result($result) uvolní z paměti všechna data, ke kterým se pomocí této proměnné dá přistoupit (typicky celou vrácenou tabulku).
DaMage:
dávnejšie DGX písal o PHP memory leaks a v rámci tohto bugu je použitie unset asi uplne zbytočné... daný problém je o tom, že PHP zruší referenciu na data, ale pamäť stále zaberajú.
No podľa mňa by sa unset mal používať, pretože v buducnosti sa to možno zmení...
DaMage:
oprava, ospravedlnujem sa za ciastocne zavadzanie... teraz som si pozrel ten bug na php.net a týka sa len objektov a ich krížových referencii...
lukas:
Pouzivam
<?php
.
.
unset($_SESSION['valid_user']);
$session_des = session_destroy();
.
.
.
?>
Je session_destroy() spravne pouzit?
Jakub Vrána :
Volání session_destroy() smaže všechna data přiřazená k session. Pokud je informace o přihlášenosti uživatele uložená pouze ve 'valid_user', stačí volat unset($_SESSION['valid_user']).
mirino:
chi chi ja by som stel vedet ako to dam dokopy na svoju stranku lebo nerozumim ani prdlajs.
martinek:
hmmm místo grafiky sem se měl učit psát weby lol ted neudělám ani howno..
Dolnman33:
jo to jsme dva :-)
error414:
Jen takova otazka, kdyz pouzivam nezabezpeceny protokol HTTP tak se heslo a login odesila pri kazdem pozadavku na server? Pokud ano tak to neni tezke odchitit.
Jakub Vrána :
Ano. Pokud je potřeba data přenášet šifrovaně, je nejlepší použít protokol HTTPS. Ale během tohoto týdne snad vyjde článek o tom, jak bezpečné přihlašování vyřešit i na protokolu HTTP.
skypeman:
Slo by prihlasovani uzivatelu udelat pomoci cookies? Vkladali by se 2 cookies, jedna se jmenem, druha s hasem hesla...
Jakub Vrána :
Do cookie je lepší uložit nějaký identifikátor, který se k přihlášení dá použít jen dočasně. Login a hash hesla se dají použít kdykoliv, proto je lepší se tomu vyhnout.
skypeman:
Je tedy mozne do cookie ukladat session id? Ty prece jsou docasne, ale stejne v ramci sezeni...
elxter:
Mohli byste mi někdo pls pomoct s přihlášením? Za prvé tomu moc nerozumíme a za druhé, když si zkopčíme ty kódy nahoře tak to nic neudělá.
mura:
Dobry den,
sem zacatecnik, tak bych potreboval poradit. Kdyz se pokousim prejit z jedne zabezpecene stranky na jinou, musim se znovu prihlasit - potreboval bych v nejake promenne uchovavat informaci o tom, ze jsem zalogovan - da se nejak snadno upravit tento script?
Jakub Vrána :
Takovou informaci je nejlepší uchovat v session proměnné. Na začátku všech skriptů (nejlépe ve společném vloženém souboru) zavolat <?php session_start(); ?> a pak používat $_SESSION["login"] = "login přihlášeného uživatele".
LUBO:
Zdravim, pokusal som as pouzit uvedeny kod na prihlasovanie, ale zatial vzdy vypisuje chybu:
Warning: mysql_result(): supplied argument is not a valid MySQL result resource in ...
na kod:
mysql_result(mysql_query("SELECT COUNT(*) FROM uzivatele WHERE login = '$_POST[auth_login]' AND heslo = '" . md5($_POST["auth_heslo"]) . "'"), 0)
intimidant:
lidi, já taky začínám. ale není od věci najít si nejdřív nějaký informace a pak se ptát...
evidentně o tom toho moc nevíte a jednoduše jste zkopírovali kód. tohle je ukázka, musíte si to upravit pro vaše potřeby. Dokonce se divím Jakubovi, že má tu trpělivost...
projděte si třeba
http://www.linuxsoft.cz/php/ - jsou tam skvěle popsaný základy... Tenhle blog má v názvu "pro mírně pokročilé"
jinak k tomu dotazu - odkazuje to do db kde jsou uložený jména a hesla uživatelů, kteří se mohou přihlásit... asi tu db vůbec nemáš
jinak přeju pevný nervy, při programování jsou potřeba :)
Silvestr:
jo, to je taky možný, dokonce víc než nějaký uvozovky... asi 300x
Silvestr:
Zkusil bych místo jednoduchých uvozovek kolem $_POST[auth_login] použít zpětné - `...`. A pro jistotu ty vstupy i předem ošetřit, kvůli sql injection.
Juví:
Já jsem asi tupá, ale pořád to nějak nechápu-řikala jsem už i bráchovi, který tomu asponˇ rozumí, dycky jsem se posunula o krok dál, ale tady jsem se prostě sekla...
DJ Majlou:
Potřeboval bych poradit. Pohužívám přihlašování tohoto příkazu:
<?php
if (!IsSet($PHP_AUTH_USER)):
Header("HTTP/1.0 401 Unauthorized");
Header("WWW-Authenticate: Basic realm=\"heslo\"");
echo "Přístup k těmto stránkám je vázán zadáním jména a hesla. heslo:a jméno:a";
exit;
else:
if($PHP_AUTH_USER!= "a" || $PHP_AUTH_PW!= "a"):
echo "zákaz vstupu!";
die;
endif;
endif;
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2">
<meta name="GENERATOR" content="Quanta Plus">
</head>
<body>
Text, který se ukáľe kdýľ správně zadáte jméno a heslo.
</body>
</html>
Potřeboval bych vědět, jak mám docílit toho, aby se mi po správném přihlášení zobrazila ta stránka kterou chci a ne toto (Text, který se ukáľe kdýľ správně zadáte jméno a heslo.) Děkuji všem za pomoc.
Lord-DarthWADER:
tak tam dej nejaky skript na presmerovani
pafkoo:
potreboval bych radu, pouzivam ten skript se session, mam 2 uzivatele v db(admin a redaktor)..jeden ma vsechny pravomoce a druhy jen omezene..jak mam na nejake strance(v adminu) zjistit ze session promenne($_SESSION[logged]) kdo je prihlasen?? jestli admin nebo redaktor...a nebo se ten skript musi upravit? dik za rady
Jakub Vrána :
Do $_SESSION["logged"] lze místo true uložit login nebo ID přihlášeného uživatele.
Lord-DarthWADER:
nebo dej zaskrtavatko prihlasit jako admin a jestli to nezaskrtne tak ho prihlasi na loginnormal.php a jestli jo tak loginadmin.php a jestli nema ucet adminsky tak mu vypise treba: Nejsi Administrátor. Přihlas se na normálny účet
Zoufalec:
Jak je to s chováním přihlašovacího skriptu, pokud se použije tlačítko "zpět" na prohlížeči?
Příklad: Mám 2 stránky
<?php
// stránka login.php
include "../mysql_class.php";
include "../db_connect.php";
include "../funkce.php";
$steno->connect();
$steno->select();
if (($_SERVER['REQUEST_METHOD']=='POST') && (isset($_POST['log_in'], $_POST['editor_user'], $_POST['editor_pass'])))
{
$error_string='';
$_POST['editor_user']=trim($_POST['editor_user']);
$_POST['editor_pass']=trim($_POST['editor_pass']);
if ($_POST['editor_user']=='' || $_POST['editor_pass']=='') { $error_string='Chyba: Přihlašovací jméno nebo heslo nebylo zadáno.'; }
if (empty($error_string))
{
// echo $_POST['editor_user'];
// echo $_POST['editor_pass'];
$steno->query(sprintf("SELECT * FROM users WHERE user_name='%s'", quote_smart($_POST['editor_user'])));
list($user_id, $user_name, $user_password) = $steno->fetchRow();
if (!(crypt($_POST['editor_pass'],$user_password) == $user_password) || ($steno->numRows()!=1)) { $error_string='<p>Chyba: Přihlašovací jméno nebo heslo bylo zadáno chybně</p>'; }
else
{
session_start();
$_SESSION['user_id'] = $user_id;
$_SESSION['user_password'] = $user_password;
header ('Location: http://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/index.php');
exit;
}
}
}
// if (!isset($_SESSION['user_id']) || !isset($_SESSION['user_password'])) { $error_string=' '; }
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="
http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="Wed, 30 Jan 2003 21:29:02 GMT" />
<link href="styly-login.css" rel="stylesheet" type="text/css" />
<title>přihlášení</title>
</head>
<body>
<div class="celek"><h2>PŘIHLÁŠENÍ</h2>
<h3>
<?php echo $error_string ?></h3>
<form name="form1" id="form1" method="post" action="
<?php echo $_SERVER['PHP_SELF'] ?>">
<dl>
<dt>Přihlašovací jméno:</dt>
<dd><input name="editor_user" type="text" value="" size="20" maxlength="20" /></dd>
<dt>Heslo:</dt>
<dd><input name="editor_pass" type="password" value="" size="20" maxlength="20" /></dd>
</dl>
<br />
<input name="log_in" type="submit" value="Přihlásit" />
</form>
</div>
</body>
</html>
<?php
// stránka index.php
session_save_path('C:\www\editor\tmp');
session_start();
if (!isset($_SESSION['user_id']) || !isset($_SESSION['user_password']))
{
$_SESSION = array();
session_unset();
session_destroy();
header ('Location: http://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/login.php');
exit;
}
// include "check_login.php";
// echo $_SERVER['SCRIPT_NAME'];
// echo $_SERVER['SERVER_NAME'];
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="
http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="Wed, 30 Jan 2003 21:29:02 GMT" />
<title>Editor</title>
</head>
<body>
<?php
echo '<p>Přihlásil se uživatel č: '.$_SESSION['user_id'].'</p>';
echo var_dump(session_get_cookie_params());
echo var_dump(session_id());
// echo $_SERVER['SERVER_NAME'];
?>
</body>
</html>
Předpokládám, že otevřu prohlížeč na stránce index.php. Nejsem přihlášen, tudíž mě hned přesměruje na login.php. Tam se přihlásím, jsem ověřen, začnu session a přesměruji se na stránku index.php, hde jsem již ověřen a zobrazí se mi tedy obsah. A teď: Tlačítkem "zpět" u prohlížeče se vrátím na stránku login.php a zadám jméno a heslo jiného uživatele. Po přihlášení jsem sice opět vpuštěn na obsah stránky index.php, ale v datech session se objevují data původně přihlášeného uživatele. Proč ne toho druhého? Díky za odpovědi...
Kuba:
ten první je stále zapsán v sessions - neodhlásil se
Lord-DarthWADER:
chci se zeptat jestli tady se da nastavit aby se kazdy uzivatel prihlasil na jinou stranku treba meno jan heslo janicek a prihlasi se na adresu jan.php a pak treba meno jana heslo janicka a prihlasi se na janicka.php takhle a kde mam psat ty kody co sou nahore a jake programy potrebuji mit aby mi to fungovalo
Lord-DarthWADER:
No tedy spis kde mam psat ty kody a v jakem formatu mam psat ty session.
Jago:
Som začiatočník a tak možno ospravedlnte moju otázku ale nie je mi celkom jasné, ako spomínaný súbor auth.inc.php
vložím pomocou funkcie "include" do stránky, ktorá má byť ochránená pomocou session.
Ja to totiž chápem tak, že každá chránená stránka asi musí na začiatku obsahovať test, ktorý zistí, či sa jedná o prihláseného alebo neprihlaseného užívateľa.
Ak môžeš, daj nejaký jednoduchý príklad s dvomi stránkami.
Ako mám zabezpečiť, aby sa mi po overení mena a hesla zobrazila požadovaná chránená stránka, pretože môj prihlasovací skript ma smeruje vždy na prvú stránku webu ?
Ďakujem.
honza:
chci se zeptat jak to mám udělat va HTML?proaďte prosím Dík.
Štěpán Svoboda:
Doporučuji začít zde. Kniha sice pojednává o 2 verze starém PHP ale zase ji sežete v bazaru za pár korun, a pokud jde o začlenění PHP do HTML myslím že stejně zatím nemá konkurenci.
http://www.grada.cz/katalog/kniha/php/
neviem:
jak sa dava registrace na web
????
Lord-DarthWADER:
ked pisem php kody ako to mam skombinovat s html?
Lord-DarthWADER:
Skusil sem ten příklad co tam byl. Nefungovalo mi to. Mám program PHP Designer 2007 Personal i Professional, myslíš, že je vhodný? Když ne tak který bych mnel mýt?
Marty:
Tady nejde o program, jde o koupení knížky nebo přečtení nějakých tutoriálů, aby jsi vůbec věděl, co děláš. Zkus nějaký seriál pro začátečníky:
http://www.linuxsoft.cz/article.php?id_article=171 (neručím za kvalitu, počet přečtení by ji mohl indikovat, přečetl jsem první díl a čte se to dobře)
Lord-DarthWADER:
muj problem je ze kdyz subor untitled.php otevru v internet explorer vypise mi kod a ne to co sem napsal do echo "";
Lord-DarthWADER:
uz mi to funguje, ale za ty odkazy dekuju
Naprostí laik:
Ahoj, používám www stránky vytvořené na www.webgarden.cz Tam to funguje na určité bázi rubrik, panelů apod. Nevím ale, kam dát ten html kod na to přihlašování pod jedním heslem. Když to dám do určitého panelu, tabulka pro přihlašování se mi sice objeví, ale na té samé straně, kterou chci skrýt. Nevím jak to udělat. Jestli mi můžete pomoci bez odborných výrazů, byla bych vám moc vděčná. Potřebuji mé stránky prostě jen zaheslovat pod jedno heslo, aby se tam dostal jen ten, který ho zná. Moc děkuji
zoufalec2:
potřebuju něco zaheslit a nikdy jsem nepoužíval PHP. HELP !!! :-(
odepiště mi prosím na e.mail j.regal@volny.cz díky moc ;-)
napul noob:
Čau lidi. Sem trochu lama. Začal sem se učit php docela sem to i chapal ale prostě ne a ne se mi povést udělat regování a přihlašování. Jak zapisovat do databáze s tím problém nemám, ale třeba tenhle script. Měl sem připojení k databázi, pak sem tam měl tento script. Sloupce sem nazval auth_login a auth_heslo . Neim eli to je spávně. Nic méně po spuštění mi to hlásilo Fatal error na řádku, kde bylo page_header("Příhlášení"); . Nemohl byste mi někdo poslat ten scrript na mail i s tím jak mám nazvat sloupce? Moc moc prosim . Je to vlastně jediná překážka k mému prvnímu jednoduchému redakčnámu systému. Regování. Moc děkuji.
mail:j.regal@volny.cz
ps: omlouvám se za pravopisné a slohové chyby.
napul noob:
je ani jsem si nevšiml že už sem tu psal. Od té doby jsem ale udělal značné pokroky ;-)
ja:
a jak je to teda s tou chybou page_header("Příhlášení"); me to dela taky
MC:
Ahoj, poradte prosim. Reseni prihlaseni, co popisuje Jakub, jsem pouzil a funguje dobre. Problem mam ale po odhlaseni. V clanku se pise, ze staci zrusit sessions, ve kterych si eviduji info o prihlaseni uzivatele (unset nebo destroy). To samozrejme take funguje, takze po odhlaseni se na vsech strankach ukazuje nejdriv prihlasovaci formular. Jak ale zabranim, aby se kdokoliv po odhlaseni uzivatele neprihlasil znovu pomoci tlacitka Zpet v prohlizeci? Pokud totiz pres Zpet dojde az na stranku, kde puvodne uzivatel odeslal prihlasovaci udaje, tak se prohlizec proste zepta, jestli udaje chce znovu odeslat a aniz by bylo potreba vyplnit jmeno a heslo, je opet prihlasen. Samozrejme by nejspis pomohlo po odhlaseni doporucit uzivateli vypnout okno se strankou, nebo nejlepe cely prohlizec, ale to nepovazuji za reseni. Asi pristupuji k problemu spatne, protoze pres hledani napovedy na internetu jsem ho proste nedokazal vyresit. Za radu predem diky.
MC:
Diky za rychlou reakci. Potreboval sem nakopnout tim spravnym smerem, ted uz mi to je jasne.
dvdk:
no potřeboval bych nenároˇčný spůsob jak na několik obsahů přihlásit několik uživatelů
ale aby kazdy uzivatel mohj jen na jeden(ten svuj)
HanziQ:
tohle trochu nefunguje ne?
<?php
$row = mysql_fetch_assoc(mysql_query("SELECT * FROM uzivatele WHERE login = '" . addslashes($_SERVER['PHP_AUTH_USER']) . "' AND heslo = '" . md5($_SERVER['PHP_AUTH_PW']) . "'"));
if (!$row) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Basic realm="Název aplikace"');
page_header("Přihlášení");
echo "<p>Pro přístup na tuto stránku se musíte přihlásit.</p>\n";
page_footer();
exit;
}
?>
to přece pro IE nejde
Jakub Vrána :
Jde to bez nejmenšího problému. Proč by to nemělo fungovat?
Balud:
V souvislosti s tímto článkem a pak ještě s http://php.vrana.cz/ukladani-hesel.php , za které fakt díky, mě napadá jedna otázka: Jak zabezpečit heslo, které uživatel zadává do formuláře při registraci, když nemůžu nebo nechci použít https:¨
V té registrační fázi je to heslo odesláno formulářem zcela nezakryté a případný číhající útočník, ho bude vědět ještě dřív, než ho opatříme hashem. Nebo když ho zahashuju pomocí JS ještě na klientovi, tak tenhle hash pak bude uložen v DB a zase může být odchycen při odeslání z formuláře...
Nebo jsem si vykonstruoval nějakou blbost?
Balud:
To jsem četl, ale celý článek se týká situace, kdy mám uživatele už registrovaného a jeho heslo v db hashované. Já hledám řešení, jak se vypořádat s novým uživatelem, který se teprve do systému registruje. Tam nějak nevidím možnost odeslat mu výzvu vygenerovanou z otisku hesla, protože to heslo ještě neznám. Pokud to tam je, tak jsem fakt natvrdlej a prosím o pořádný kopanec :-)
Jakub Vrána :
Je to úplně na konci článku v Doplnění.
Pokud je teď v databázi uložen hash, je možné ukládat md5(hmac_md5(hash(password), challenge)).
Balud:
Ale já ten hash přece ještě nemám.
příklad: Mám uživatele Franta, který je v db a má tam otisk hesla. Není problém. Ale Franta řekl Pepovi o novém báječném webu a Pepa se chce registrovat, protože v db ještě není, tak tam nemá ani hash, ale musí mi nějak poslat to svoje heslo, které bude v budoucnu používat.
No, možná jsem zbytečně paranoidní, ale co jednoduššího než odposlechnout heslo při registraci by mohl útočník udělat?
Jakub Vrána :
Na server se při registraci pošle md5(hmac_md5(password, challenge)) (v tvém případě md5(hmac_md5(hash(password), challenge)), aby se na tento systém dali převést i stávající uživatelé).
Pokud to stále nechápeš, stáhni si Proof of Concept, obsahuje i registraci.
Balud:
Díky, už jsem to pochopil. Omlouvám se za "pitomé" otázky.
Kubees:
Dobrý den, mám následující problém:
Mám na stránkách jednoduchý formulář na přihlašování uživatelů pomocí session. Všechno funguje, ale stránka není validní podle normy XHTML 1.0 Strict, protože server mi automaticky cpe do formuláře skrytý input s identifikátorem session. Nevíte jak se s tímto problémem vypořádat?
Pro lepší představu kód:
(zjednodušený)můj kód:
<?php
session_start();
ini_set('arg_separator.output', '&');
?>
<form action='login.php' method='post'>
<p>
login:
<input type='text' name='login' />
heslo:
<input type='password' name='password' />
</p>
</form>
kód po průlezu serverem:
<form action='login.php' method='post'>
<input type='hidden' name='SESSID' value='b43b6e690da6f8c4761ef0ea15d53cba'>
<p>
login:
<input type='text' name='login' />
heslo:
<input type='password' name='password' />
</p>
</form>
Jakub Vrána :
Doporučuji vypnout session.use_trans_sid.
Lukáš:
Ahoj,
zkuste mi prosím někdo poradit. Můj problém spočítvá v tom, že po odhlášení se pomocí tlačítka zpět, dostanu na zaheslované stránky. Sice tam nemůžu nic udělat, ale vidim obsah.
Konkrétně (zjednodušeně): na každé php stránce mam session_start (v .htaccess session.use_trans_sid off).
Pokud se přihlásim (přes jméno, heslo), naplnim proměnnou $_SESSION["nick"] na nějakou hodnotu. Na začátku stránky, která má byt vidět jen pro přihlášené, testuju, zda v ní něco je. Pokud ano, zobrazim tajný obsah, pokud ne, nezobrazim.
Za tlačítkem "Odhlásit" se skrývá tento kod:
unset($_SESSION["nick"]);
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
session_start();
session_unset();
session_destroy();
header("Location: http://".$_SERVER["SERVER_NAME"]."".urldecode($path));
exit;
který ale nezabrání tomu, že když pak stisknu "Zpět", tak vidim obsah tajných stránek - čemuž bych rád zabránil.
děkuji za případné rady
Jakub Vrána :
Prohlížeče při pohybu v historii obchází cache, takže se požadavek o opětovné zobrazení stránky na server vůbec nedostane.
Otázka je, zdali to něčemu zásadně vadí. Pokud ano, tak nezbývá než uživatele informovat o tom, že by po odhlášení měli zavřít panel prohlížeče.
abc:
Při odhlašování napište:
session_start();
session_unset();
session_destroy();
Na tlačítko zpět to trochu pomůže.
abc:
A přesměrovat na stejnou stránku.
Kubees:
Dobrý den,
zjistil jsem, že v prohlížeč Avant Browser má problém s php funkcí session_regenerate_id(); Při jejím použití ze ztratí Session spojení mezi klientem a serverem.
Kvůli klientovi s tímto prohlížečem jsem session_regenerate_id(); při přihlášení nahradil dvojicí
session_destroy(); session_start(); která funguje v pořádku. Chtěl bych se zeptat, zda je toto řešení korektní.
Díky za odpověď.
Jakub Vrána :
Nechápu, co by prohlížeči mohlo vadit. Problém se session_destroy() je ten, že odstraní všechna session data.
Lukas:
Ahoj,
před nedávnem mi na stránkách hlásí antivirák nějaký vir, dle poskytovatele webhostingu bych si měl lépe ošetřit skript na přihlášení.
Můj skript je následující a je uložen v samostatném souboru login.php, který vkládám na každé stránce. Samotné ověření na stránkách kde má být přístup pouze pro přihlášeného uživatele, tak používám jednoduchou podmínku if(!isset($_SESSION['uzivatel']) zobraz hlášku.
soubor login.php
<?php session_start();
$loginform=true;
$logoutform=false;
if(isset($_SESSION['user']) AND (!$_POST['logout']))
{
$loginform=false;
$logoutform=true;
echo "Pøihlášený uživatel: ".$_SESSION['user'];
}
else
{
if($_POST['login'])
{
$db = MySQL_connect("server", "user", "heslo") or die("Nezdarilo se spojeni s databazi");
MySQL_select_db("databaze");
$dotaz = mysql_query("SELECT * FROM uzivatele WHERE user='".$_POST['uzivatel']."' and pass='".$_POST['heslo']."'");
if(mysql_num_rows($dotaz)==0)
{
echo "<span>Špatné jméno uživatele<br>nebo heslo</span>";
$loginform=true;
$logoutform=false;
}
else
{
$obsah = mysql_fetch_array($dotaz);
$_SESSION['user']=$obsah[4];
$loginform=false;
$logoutform=true;
echo "Pøihlášený uživatel:<br><br>".$_SESSION['user'];
}
}
}
if($_POST['logout'])
{
unset($_SESSION['user']);
$loginform=true;
$loginoutform=false;
}
?>
<?php if($loginform): ?>
<form action="index.php" method="POST">
Uživatel<br><input type="text" maxlength="15" name="uzivatel"><br>
Heslo<br><input type="password" maxlength="15" name="heslo"><br><br>
<input type="hidden" name="login" value=true>
<input class="button" type="submit" value="Pøihlásit">
</form>
<?php endif?>
<?php if($logoutform): ?>
<form action="index.php" method="POST">
<input type="hidden" name="logout" value=true>
<input class="button" type="submit" value="Odhlásit">
</form>
<?php endif?>
Myslíte, že by pomohlo přidat session_regenerate_id() před $_SESSION['user']=$obsah[4];? Popř. vidíte tam někde závažnou chybu? Zkusím popř. zahashovat jestli to pomůže.
díky moc za každý názor :-)
Jakub Vrána :
Většina těchto virů se na stránky dostane spíš přes špatně zabezpečené FTP připojení. Nedávno se třeba hodně rozšířil vir, který vykrádal hesla z Total Commandera.
Lukas:
Děkuji Jakube za tip, přistupuji na FTP právě přes Total Commandera.
Jinak myslíte, že můj způsob přihlášení je relativně z bezpečnostního hlediska v pořádku nebo byste doporučil ošetřit to jinak?
děkuji
Lukáš
Lukas:
Ještě bych pro jistotu zmínil co mi hlásí ten antivirák viz:
File name: C:\Documents and Settings\Marta\Local Settings\Temporary Internet Files\Content.IE5\P3N801RZ\index[1].htm
>
> Threat name: Virus found JS/Obfuscated
> Detected on open
Myslíte tedy, že to není špatným zabezpečením přihlašovacího skriptu?
viera:
dobry den,
mohli by ste mi, prosim, poradit s nasledovnym? v php robim mensi informacny system (zatial offline), kde sa pouzivatelia prihlasuju cez sessions. ak pracuje pouzivatel sam, je vsetko v poriadku. ak ale otvorim novu kartu prehliadaca a prihlasim sa ako iny pouzivatel a nasledne sa vratim k povodnemu, jeho udaje sa zmenia na pouzivatela cislo 2.
neviem, ci to popisujem dostatocne, preto uvediem konkretny priklad: prihlasim sa ako "viera", cez nejaky ten login a heslo. otvorim nove okno a prihlasim sa ako "ondrej". vratim sa k prvemu oknu, kde som prihlasena ako "viera", kliknem na nejaku moznost menu - a uz som tu ako "ondrej".
je to len tym, ze je system offline a vsetka pouzivatelska aktivita sa odohrava na jednom pocitaci?
vopred dakujem za odpoved 8)
Jakub Vrána :
Jeden prohlížeč sdílí sadu cookies, tím pádem i session proměnné. Pokud by ses k aplikaci připojil ze dvou různých prohlížečů (např. na dvou různých počítačích), tak na sobě budou nezávislé.
viera:
ďakujem za odpoveď, už je mi to jasné 8) vlastne ani nepotrebujem umožniť prihlasovanie viacerých používateľov z jedného pc naraz, išlo mi len o to, aby táto situácia nenastala aj v reáli - ešte som takýto systém neimplementovala, tak som si nebola istá.
dandy89:
zdravim, mam podobny problem jako tu uz nekdo psal, ale nebyla na nej dana odpoved. Vypisuje mi to tuto chybu : Warning: mysql_result(): supplied argument is not a valid MySQL result resource in C:\ComplexWebServer\http_docs\diskuze.php on line 6
Pripominam, ze jsem mnohokrat kontroloval, jestli k sobe pasuji udaje v kodu a v databazi. prosim o odpoved
Štěpík:
Cau prosím mohl byste mi nekdo poradit, jak mám nastavit odhlašování uživatelů, kteří jsou přihlášeni na webové stránky, kterré jsou zabezpečené pomocí .htaccess. Pokud se přihlásím, a dám zpět a dnovu kliknu na vstoupit do galerie, tak se už neobjeví přihlašovascí dialog... nevíte nekdo jak na to prosím?
Jakub Vrána :
Pokud vím, tak to z aplikace spolehlivě nejde. V některých prohlížečích funguje odkaz http://xxx@example.com, kde xxx je neexistující uživatel, ale nefunguje to všude. V některých prohlížečích si to uživatel může zrušit sám (např. ve Firefoxu pomocí Ctrl+Shift+Del), ale jedinou univerzální možností je zavřít prohlížeč.
v6ak:
Četl jsem i něco o hlavičce unauthorized, ale taky nevím, jak moc to je univerzální.
kozotoč:
poznámka k použitému HTML kódu v příkladu:
* myslím (ale je to věc subjektivní), že by bylo o kousek přehlednější, kdyby těch pár řádek s formulářem bylo mimo php kód
* vše uvnitř <form..> ... </form> bych ještě obalil do <div> nebo (lépe) <fieldset>.
Prdlořeznictví Krkovička, n. p.:
Chtěl bych se zeptat, jak se na takto zabezpečené stránky přihlásit automaticky, pomocí skriptu (když přihlašovací údaje samozřejmě znám).
czjaromir:
To teď taky řeším diskuzi jsem zběžně prohlédl a potřebuji se přihlásit do mašiny pouhým poklepáním na ikonu.Informace o tom že se nelze přihlásit pomocí http://neexistuje@www.example.com mi sice pomohla v tom že jsem to přestal lámat ale stále nevím jak na to. Myslím kamerový server.
Help:
Mám problém s přihlášením...po přihlášení by se stránky měli přesměrovat na admin.php ale pokaždé se vrátí k přihlášení jako by se do session nic nezapsalo...(doma na wampu mi to jde bez problému ale na forpsi ne)
<?php
include('connect.php');
if (isset($_SESSION["logged"])) {
header("Location: admin.php");
}
if (isset($_POST["auth_login"])) {
if (mysql_result(mysql_query("SELECT COUNT(*) FROM prihlaseni_admin WHERE login = '" . mysql_real_escape_string($_POST["auth_login"]) . "' AND heslo = '" . md5($_POST["auth_heslo"]) . "'"), 0)) {
session_regenerate_id(); // ochrana před Session Fixation
$_SESSION["logged"] = $_POST["auth_login"];
header("Location: admin.php");
}
}
if (!isset($_SESSION["logged"])) {
if (isset($_POST["auth_login"])) {
echo "<p>Neplatné přihlašovací údaje.</p>\n";
}
echo "<form action='' method='post'>\n";
echo "<p>Login: <input name='auth_login' maxlength='30' /></p>\n";
echo "<p>Heslo: <input type='password' name='auth_heslo' /></p>\n";
echo "<p><input type='submit' value='Přihlásit' /></p>\n";
echo "</form>\n";
exit;
}
?>
RadekR:
Narazil jsem na první HEADER a dál to nelouskám. Měla by tam být absolutní adresa.
Help:
Proc absolutni kdyz je to ve stejnem adresari??
Michal:
Já bych to viděl asi takto:
<?php
session_start();
include "mysql_connect";
if (isset($_GET["logout"])) {
unset($_SESSION["logged"]);
}
if (isset($_SESSION["logged"])) {
header("Location:".$_SERVER["DOCUMENT_ROOT"]."/admin.php");
exit;
}
if (isset($_POST["auth_login"])) {
if (mysql_result(mysql_query("SELECT COUNT(*) FROM prihlaseni_admin WHERE login = '" . mysql_real_escape_string($_POST["auth_login"]) . "' AND heslo = '" . md5($_POST["auth_heslo"]) . "'"), 0)) {
session_regenerate_id(); // ochrana před Session Fixation
$_SESSION["logged"] = $_POST["auth_login"];
header("Location:".$_SERVER["DOCUMENT_ROOT"]."/admin.php");
exit;
}
}
if (!isset($_SESSION["logged"])) {
if (isset($_POST["auth_login"])) {
echo "<p>Neplatné přihlašovací údaje.</p>\n";
}
if (isset($_GET["logout"])) {
echo "<p>Odhlášen.</p>\n";
}
echo "<form action='' method='post'>\n";
echo "<p>Login: <input name='auth_login' maxlength='30' /></p>\n";
echo "<p>Heslo: <input type='password' name='auth_heslo' /></p>\n";
echo "<p><input type='submit' value='Přihlásit' /></p>\n";
echo "</form>\n";
}
?>
1) Proč absolutní se už tady na blogu mockrát řešilo, takže hledej.
2) Nevím jestli spoléháš na automatické spuštění session, nebo to máš v tom includovaném souboru s mysql spojením, každopádně bych na začátek dal session_start().
3) Po přesměrování se musí ukončit provádění skriptu (exit).
Jinak jsem si to na localu odzkoušel a funguje to. Místo mysql spojení jsem si tam dal jenom ověření v rámci toho if, ale pokud to testování s mysql je správně (vypadá to na Jakubův vzor) tak to jde Ok.
Dodal jsem tam odhlášení.
Nevím jestli se to tady už řešilo, ale myslím že tu někde padlo něco ve smyslu, že je lepší jako session identifikátor použít nějaký náhodný řetězec nebo tak.
Help:
kdyz dam absolutni tak mi to napise The requested URL /httpd/html/flipr_investcz/www/admin.php was not found on this server. ....a opravdu se soubor tak jmenuje a je v te slozce www tak ja nevim
Michal:
Napiš sem co ti vypíše
<?php echo (__DIR__); ?>
Michal:
Zajímavé. Tak tam dej do toho přesměrování celou adresu ručně mno.
Mirek:
Mám trochu problém s HTTP AUTENTIFIKACI, mám kamerový server který na určité drese na zavolaní vypouští prostřednictvím CGI aktuální JPEG obraz z kamer, když na tu adresu lezu z prohlížeče dostanu se tam přes HTTP AUTH se jménem a heslem ale jak to udělat když na tu adresu chci posílat např. PHP skript? jak mu mám nastavit informaci o jménu a heslu aby se HTTP AUTH provedla? Předem díky moc za radu
Mirek:
Už sem to vyřešil přes CURL
Jakub Vrána :
Mělo by stačit přistoupit k http://user:pass@example.com/.
Marek:
Trosku nebezpecne do $_SESSION["logged"] ukladat jen true bych tam ukládal jeste aspon IP adresu popřípadně jeste jakej je to prohlízec a operacni system co kdyz nejákym zpusobem nekomu vykradu cookies(treba xss utokem) a vlozim si ho do prohlizece u sebe tak tu ranu jsem prihlasenej za nekoho jinyho....
Jakub Vrána :
IP adresa se může měnit, navíc ji často sdílí více uživatelů. Identifikátor prohlížeče nemá téměř žádnou vypovídací hodnotu a kupodivu se také může měnit (např. v Opeře velmi snadno).
Přijďte si o tom popovídat na školení bezpečnosti.
jt:
problem zní takto uživatel se přihlásí a pak je tam nějaká proměná a ta má jinou hodnotu u každého jak udělat aby se každému uzivateli změnila jen jeho proměnná
Jakub Vrána :
Nejlepší bude ukládat si hodnotu do databáze spolu se záznamem o uživateli.
Luca:
dobrý den mám dotaz jak by jste udělali následující.. mám ip kameru která neumožňuje přístup k obrázkům bez jména a hesla. to znamená že normálně bych jméno a heslo odesílal pomocí http://jmeno:heslo@www.stranka.cz jenže to bohužel msie už neznemožňuje a tak bych rád nějakým způsobem skriptem bez vědomí uživatele se na kameru přihlásil aby se uživateli rovnou bez zadávání hesla zobrazil obrázek. Jde to nějak ? jak prosím.
Sarka:
Dobrý den, mám tabulku s přihlášením, ale nevím jak tam vložit něco, co by zaručovalo že se dotyčný přihlásí a je taam registrovaný, nebo jestli existuje k přihlašovací tabulce nějaká registrační tablka která zapíše automaticky toho dotyčného pro přihlašování. Je mi to jedno, hlavně mě zajímá jestli to nějak jde.:) Děkuji
Anonimka:
Já nevím co s tím je, ale mě na mé stránky jde jen login a heslo, ale ne registrace.
smrdící epidemie:
typo: Příhlášení --> Přihlášení
Diskuse je zrušena z důvodu spamu.