Autor Zpráva
gardener
Profil
Zdravím,
Napsal jsem si skript pro přihlašování uživatelů, který by se dal rychle nasadit na website v případě potřeby, nejsem si ale moc jistý jak je to s efektivností kódu a jeho bezpečností.
Takže pokud by někdo tušil jak to napsat lépe, nebo čeho se vyvarovat budu jedině rád za připomínky.

Jak pracuje?
Dta z formu vezmeme, ověříme, zda byla vubec zadána, pokud ne, informujeme, pokud ano, zavoláme fci pro ověření se dvěma vstupními parametry.
fce si "šáhne do tabulky" uživatele apokud najde víc ja 0 řádků shody nastaví potřebné hodnoty pro session a končí, na základě nastavených hodnot, rozlišíme zda je to uživatel, admin, nebo omyl a přesměrováváme.


Díky za každou radu.

Form
<!--
CONNECT TO THE DB
-->
<?php

include_once("db_pripoj.php");
include_once("db_vytvor.php");
include_once("functions.php");
?>
<!--
CATCHING $GET AND INCLUDING CONTENT
-->
<?php
$action = $_GET["action"];
if ($action == "over_usera") {include ("over_usera.php");}
?>
<form action="index.php?action=over_usera" id="" class="center" name="form" method="post" enctype="multipart/form-data">
  <fieldset>
  <legend>Přihlášení uživatele</legend>
  <label for="prijmeni">Login:</label>
  <br />
  <input type="text" id="log" name="log" />
  <br />
  <label for="heslo">Password:</label>
  <br />
  <input type="password" id="heslo" name="password" />
  <br />
  <br />
  <?php   
//Only if form is submitted
//Pass throught array
if (isset($action))
{
$arr = $hlaska_vlozeni;
foreach ($arr as $value) 
{
echo("$value<br/>");
}
}
unset($value); // break the reference with the last element
?>
  <input name="submitt" type="submit" value="Přihlásit" />



Overeni

<?php session_start(); ?>
<?php
$prihlasen_admin= "admin.php";
$prihlasen_uzivatel= "uzivatel.php";
$neprihlasen= "index.php";
error_reporting(E_ALL); //Reporting about all errors
$log = (mysql_real_escape_string($_POST["log"]));
$password = (mysql_real_escape_string($_POST["password"]));
if (empty($log) | empty($password))
{
    $hlaska_vlozeni[] = "Nevyplnili jste potřebné údaje";
} 
else
{
//Call function for verifu, that user is admin,normal user or not
overeni($log, $password);
if(($_SESSION['prihlasen'] == 1) & ($_SESSION['is_admin'] == 1))
{
 echo "<script>location.href=\"$prihlasen_admin\";</script>";
}
else if(($_SESSION['prihlasen'] == 1) & ($_SESSION['is_admin'] == 0))
{
 echo "<script>location.href=\"$prihlasen_uzivatel\";</script>";
}
else 
{
 $hlaska_vlozeni[] = "špatně zadané údaje";
}
}
?>


Fce kterou voláme

<?php
//FUNKCE PRO OVERENI ZDA JE UZIVATEL ADMIN, CI NENI, PODLE TOHO ZDA MA V TABULCE UVEDENO 0 CI 1
//POKUD SE VSE OSTATNI SHODUJE, T. PRIJMENI A MAIL, TAK PRESMERUJEME BUD NA ADMIN.PHP NEBO NA VYPIS.PHP
function overeni($log, $password)
{
    $_SESSION['prihlasen'] = 0;
    $_SESSION['is_admin'] = 0;
    $q = mysql_query("SELECT je_admin FROM uzivatele WHERE log='$log' AND heslo='$password'");
    if (mysql_num_rows($q) > 0) {
        list($jeadmin) = mysql_fetch_row($q);
        if ($jeadmin) {
            $_SESSION['prihlasen'] = 1;
            $_SESSION['is_admin'] = 1;
			
			
        } else {
            $_SESSION['prihlasen'] = 1;
			$_SESSION['is_admin'] = 0;
        }
    } 
	else {
	
        $_SESSION['prihlasen'] = 0;
		$_SESSION['is_admin'] = 0;
		return false;
    }
}

?>
tiso
Profil
gardener - začni tým, že nebudeš ukladať heslo do databázy v plain forme, ale iba jeho hash (md5, sha1, ...)
TomášK
Profil
tiso
Ještě se do dá vylepšit o salt (neznám adekvátní překlad) a do databáze ukládat md5(salt+password) - kvůli rainbow tables.

Ke kódu:
* rozhodni se, jestli chceš psát česky nebo anglicky, kombinace vypadá dost příšerně (over_usera apod.)
* dodržuj odsazení, máš dvakrát za sebou na začátku řádku } (pokud se to nerozhodilo až při kopírování)
* odstaň výstup před session_start()
* zjisti, jaký je rozdíl mezi | a ||
* error_reporting(E_ALL) považuju za rozumné při vývoji, na produkčním serveru to nemá co dělat - uživatel by se měl dozvědět, že nastala jaká chyba, ale chybový výpis by se mu zobrazit neměl
* kód by na mnoho místech šel upravit, aby byl čitelnější.
gardener
Profil
Díky, určitě se na to zaměřím
S tím MD5..tam jde ale o jednostranné šifrování ne? Takže pokud bych potřeboval zjistit, pouze z db heslo, tak jak jej zadal uzivatel, tak bych asi nepochodil že?
TomášK
Profil
S tím MD5..tam jde ale o jednostranné šifrování ne? Takže pokud bych potřeboval zjistit, pouze z db heslo, tak jak jej zadal uzivatel, tak bych asi nepochodil že?
Ano, md5 je jednostrané šifrování, ale ono to nevádí - dokonce víc, je to žádoucí. Ty nepotřebuješ vědět, jaké má uživatel heslo. Víc než to, ty to nechceš vědět. Připustíme-li možnost, že někdo pronikne do databáze, pak tam najde jen md5 hashe hesel - ovšem ty mu budou na nic, protože z nich nezjistí přímo ta hesla - nedokáže se přihlásit pod libovolným uživatelem. Jediné, kdy by se mohlo hodit znát přímo heslo, je situace, kdy ho uživatel zapomněl. Pak ale nic nebrání tomu vygenerovat nové heslo.
fuckin
Profil *
ta funkce overeni me prijde ponekud zmatena, proc vracis false ale true nikoli? Nebude lepsi z toho udelat rovnou proceduru ? Nebo funkci ktera bude vracet true a false a pak nasledne po zjisteni true nebo false zapsat session?


- nekombinuj anglictinu a cestinu dohromady
- vis jaky je rozdil mezi | a || ?
- vytvor spis funkci overit ktera bude vracet true a false a funkci jeAdmin ktera bude taky boolean
-neumis odratkovavat text (beru zpet jestli je to timto forem)
- o sha1 ani nemluve...
gardener
Profil
o.k zaimplementuji tam MD5, bude to tak lepší.

Co se týče připomínek:

- nekombinuj anglictinu a cestinu dohromady
(Souhlas, psal jsem to v češtině abych se dobře orientoval při psaní ale vždycky jsme dostal nějaký cuk to psát angicky, takže z toho vznikl tenhle hybrid. )
- vis jaky je rozdil mezi | a || ?
(No myslím, že u | je potřeba aby byly splněny obě dvě podminky a u || se jedná o neexkluzivní log. součet takže bude vracet true, pokud bude min. jedna hodnota správně)
- vytvor spis funkci overit ktera bude vracet true a false a funkci jeAdmin ktera bude taky boolean
(Nevím, jestli to není spíš zesložitění ty návratové hodnoty T a F jsem tam ale opravdu zbytečně)
-neumis odratkovavat text (beru zpet jestli je to timto forem)
(Zřejmě fórem)
- o sha1 ani nemluve...
Nox
Profil
(No myslím, že u | je potřeba aby byly splněny obě dvě podminky a u || se jedná o neexkluzivní log. součet takže bude vracet true, pokud bude min. jedna hodnota správně)
Ne-e, v PHP to je často tak, že 1 operátor je akce a 2 je porovnání...čili | by měl imho být logický součet dvou členů, což ve většině případů v podmínce nechceš
Stejně tak na několika místech máš místo && jen logický součin...ikdyž výsledek by měl být asi stejný

Obě podmínky splněny: &&
Alespoň 1: ||
imploder
Profil
Zdá se mi, že tam chybí zapamatování ID uživatele v $_SESSION, aby pak šlo zjistit, který je to uživatel.

gardener
- vis jaky je rozdil mezi | a || ?
(No myslím, že u | je potřeba aby byly splněny obě dvě podminky a u || se jedná o neexkluzivní log. součet takže bude vracet true, pokud bude min. jedna hodnota správně)

Nn, | je bitový součet. Jako logický OR bude fungovat jenom s operandy typu bool.
Lamicz
Profil
Připustíme-li možnost, že někdo pronikne do databáze...
A ja budu tvrdit, ze sifrovani hesel, pokud se dane heslo nikde nepredava (napr. v SESSION nebo se neuklada do COOKIE), je k nicemu. Kdyz se Ti nekdo dostane do databaze, muze si udelat stejne co chce, svym libovolnym uctem pocinaje a smazanim cele databaze konce. Proc by proboha zjistoval nekomu ucet a lamal md5??.
Sifrovani hesel je dobry jenom na jedinou vec - pres SQL injekci nebo XSS se nekam vypise tabulka s ucty. Tot vse.
pEeLL
Profil
Lamicz
Kdyz se Ti nekdo dostane do databaze, muze si udelat stejne co chce, svym libovolnym uctem pocinaje a smazanim cele databaze konce. Proc by proboha zjistoval nekomu ucet a lamal md5??.

a ted si vem ze tento uzivatel by mel stejne jmeno treba pro svuj mail, kde by mel ulozene maily z ruznych jinych registraci ve kterych by byla ruzna hesla nebo jine citlive informace. pokud v databazi najde jen hash tak maximalne ovladne dany ucet/web.
Lamicz
Profil
pEeLL
Tohle je ale nejvic blbost daneho uzivatele, a navic pokud je to heslo jednoduchy (coz ono vetsinou je), tak je ten hash stejne naprd. Do te databaze se proste nikdo cizi dostat nesmi. Tecka. BTW proto se na hodne mistech hesla generuji a nejdou menit.
Visitor
Profil *
Nejde to ze zapisu poznat a nebylo zmineno...

- indexy nad databazi
-- unikatni nad "log"
-- a aby slo rychle vyhledavat, tak index nad "log" + "heslo"
imploder
Profil
Lamicz
Tohle je ale nejvic blbost daneho uzivatele, a navic pokud je to heslo jednoduchy (coz ono vetsinou je), tak je ten hash stejne naprd.
Na to se právě heslo před zahashováním solí, pak to tak jednoduché není.

Do te databaze se proste nikdo cizi dostat nesmi. Tecka.
Může nastat případ, kdy si např. pomocí sql-injection někdo zpřístupní údaje z databáze, ale jenom pro četení (tj. něco se mu vypíše). Pokud je nedostatečně zabezpečený jenom nějaký skript tahající data z databáze a ne zapisující a SQL-injectionem jde jenom nějaká data vytáhnout, tak má smysl mít hesla nečitelná. Útočník si tak akorát přečte něco z databáze, ale žádný uživatelský účet neovládne.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

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