Jednoducha autentifikacia uzivatelov alebo A je to

21.09.2002 19:08

Urcite ste sa stretli s ulohou zabezpecit svoje stranky alebo pristup do databazy len pre urcitych uzivatelov. Existuje mnozstvo jednoduchych a peknych sposobov, najma ak ste administratorom weboveho a databazoveho serveru v pravom zmysle slova - teda mate moznost pristupu aj k samotnemu OS. Co vsak, ak sa naskyta len PHP, HTML a MySQL v obmedzenej miere, pripadne know-how na nizkej urovni?

Poziadavky na riesenie ulohy boli nasledovne:

- \"v jednoduchosti je krasa!\"
- vyuzit jednoduche funkcie PHP (zlozite konstrukcie su pricinou zacyklenia sa programatora)
- pouzit len zaklady databazy MySQL (vytvorenie tabulky, vyberovy a pridavaci dopyt)
- nepouzivat cookies (mnohi surferi cookies v priehladaci s oblubou vypinaju, pripadne si starsie verzie browserov s cookies neporadia)
- nepouzivat zabezpecovacie funkcie HTTP protokolu (dobre sa to cita, ale je to dost ubohe)
- vsetky formulare vyhodnocovat v \"index.php\"
- strucne informovat tvorcu skriptu, databazovych tabuliek a casto aj uzivatela v jednej osobe na chyby, ktore mozu nastat
- a samozrejme aj dobra citatelnost skriptov i vysledneho \"cisteho\" HTML nie je na skodu (zalezi na zvykoch programatora).

Pozrime sa teda na jedno z moznych rieseni (lebo vzdy existuje lepsie, bezpecnejsie, atd., atd.)... ;-)

V prvkom kroku si vytvorime skript \"db.php\", ktory bude zabezpecovat pripojenie a odpojenie od databazi. <?function db_open() // funkcia otvarajuca pripojenie  {  @$link = mysql_connect(\"server\",\"uzivatel\",\"heslo\"); // pripojenie k databaze  @$conn = mysql_select_db(\"nazov_databazy\"); // vyber databazy  if (!$link || !$conn)    {     head(); // hlavicka stranky    // ak sa niektora z predchadzajucich akcii nepodari sposobi chybovu hlasku    require \"./err_open_db.php\";    foot(); // pata stranky    exit;    }  }function db_close() //funkcia zatvarajuca databazu  {  MySQL_Close();   }?>V dalsom kroku to bude skript \"general.php\", ktory bude obsahovat funkcie head() a foot(). Prva vypise, ako ste sa uz urcite dovtipili, hlavicku HTML dokumentu a druha jeho patu. <?function head()  {  echo \"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">nn\";  echo \"<HTML>n\";  echo \"<HEAD>nn\";  echo \"  <LINK REL=\"StyleSheet\" HREF=\"./main.css\" TYPE=\"text/css\">nn\";  $GMTDateTime = GMDate(\"D, d M Y H:i:s\") .\" GMT\";  echo \"  <META HTTP-EQUIV=\"Cashe-Control\" CONTENT=\"no-cashe, must-revalidate\">n\";  echo \"  <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; CHARSET=ISO-8859-2\">n\";  echo \"  <META HTTP-EQUIV=\"Last-Modified\" CONTENT=\"\"; echo $GMTDateTime; echo\"\">n\";  echo \"  <META HTTP-EQUIV=\"Expires\" CONTENT=\"\"; echo $GMTDateTime; echo\"\">nn\";  echo \"  <TITLE>pokus</TITLE>nn\";  echo \"</HEAD>nn\";  echo \"<BODY BGCOLOR=\"#336699\" LEFTMARGIN=\"10\" RIGHTMARGIN=\"10\" TOPMARGIN=\"10\" MARGINWIDTH=\"0\" MARGINHEIGHT=\"0\">nn\";  }function foot()  {  echo \"</BODY>n</HTML>\";  }?>Nasledne, aby sme si \"trochu oddychli od PHP\" mozme prejst k tvorbe databazovych tabuliek.

Aby som sa trochu vyhol vseobecnostiam, pouzijem priklad z praxe. Urcite kazdy z nas ma doma uctihodnu zbierku albumov v MP3. Takze, preco si nezbuchat konecne nejaky zoznam, hodit to na I-net a vytlct z toho nejake koruny predajom napalenych CD-R? No zabite ma, aj ked je to nelegalne, hlavne su vzdy aj tak chechtaky!

Budeme vytvarat dve tabulky \"albums\" a \"users\". CREATE TABLE albums (id INT(5) NOT NULL PRIMARY KEY AUTO_INCREMENT,artist VARCHAR(255) NOT NULL,album VARCHAR(255) NOT NULL,mb FLOAT(7,2) NOT NULL,time TIME NOT NULL,cd_number VARCHAR(4),cd_count CHAR(1),note VARCHAR(255));id, artist, album - asi nemusim vysvetlovat, nazvy poli hovoria za seba
mb - velkost celeho albumu v Mbajtoch (ked sa budu palit datove CD)
time - celkovy cas albumu v tvare hh:mm:ss (ked sa budu palit hudobne CD)
cd_number - velka zbierka byva casto rozhadzana po niekolkych CD, takze usporiadanie je organizacne plus
cd_count - nie je neobvykle, ze vychadzaju 2-CD
note - poznamka nikdy neuskodi CREATE TABLE users (name VARCHAR(15) NOT NULL PRIMARY KEY,pass VARCHAR(15) NOT NULL);Aby sme sa mohli prihlasit ako niekto, vlozime si do databazy uzivatela. INSERT INTO users (name, pass) VALUES ('meno','heslo');Po kratkom oddychu s MySQL si mozme este polebedit aj s HTML v podobe vytvorenia chybovych hlasok:

- Neboli zadane vsetky potrebne udaje! (err_ins.php)
- Pokus o pripojenie k databaze zlyhal! (err_open_db.php)
- Nespravne meno a heslo! (err_pass.php) <DIV ALIGN=\"CENTER\"><TABLE>  <TR>    <TD>Neboli zadane vsetky potrebne udaje!</TD>  </TR></TABLE></DIV> <DIV ALIGN=\"CENTER\"><TABLE>  <TR>    <TD>Pokus o pripojenie k databaze zlyhal!</TD>  </TR></TABLE></DIV> <DIV ALIGN=\"CENTER\"><TABLE>  <TR>    <TD>Nespravne meno a heslo!</TD>  </TR></TABLE></DIV>A takmer na koniec by sme sa mohli dat do tvorby formularov \"insert.php\" a \"login.php\". <DIV ALIGN=\"CENTER\"><TABLE>  <FORM ACTION=\"./index.php\" METHOD=\"POST\" ACCEPT-CHARSET=\"ISO-8859-2\" NAME=\"insert\">  <INPUT TYPE=\"HIDDEN\" NAME=\"name\" VALUE=\"<? echo $name ?>\">  <INPUT TYPE=\"HIDDEN\" NAME=\"pass\" VALUE=\"<? echo $pass ?>\">  <TR>    <TD>Interpret:</TD>    <TD>      <INPUT TYPE=\"TEXT\" NAME=\"artist\" SIZE=\"30\" MAXLENGTH=\"255\" TABINDEX=\"1\">    </TD>  </TR>  <TR>    <TD>Album:</TD>    <TD>      <INPUT TYPE=\"TEXT\" NAME=\"album\" SIZE=\"30\" MAXLENGTH=\"255\" TABINDEX=\"2\">    </TD>  </TR>  <TR>    <TD>Velkost v MB:</TD>    <TD>      <INPUT TYPE=\"TEXT\" NAME=\"mb\" SIZE=\"30\" MAXLENGTH=\"9\" TABINDEX=\"3\">    </TD>  </TR>  <TR>    <TD>Celkový cas:</TD>    <TD>      <INPUT TYPE=\"TEXT\" NAME=\"time\" SIZE=\"30\" MAXLENGTH=\"6\" TABINDEX=\"4\">    </TD>  </TR>  <TR>    <TD>Cislo CD-R:</TD>    <TD>      <INPUT TYPE=\"TEXT\" NAME=\"cd_number\" SIZE=\"30\" MAXLENGTH=\"3\" TABINDEX=\"5\">    </TD>  </TR>  <TR>    <TD>Pocet CD-R:</TD>    <TD>      <INPUT TYPE=\"TEXT\" NAME=\"cd_count\" VALUE=\"1\" SIZE=\"30\" MAXLENGTH=\"1\" TABINDEX=\"6\">    </TD>  </TR>  <TR>    <TD>Poznamka:</TD>    <TD>      <INPUT TYPE=\"TEXT\" NAME=\"note\" SIZE=\"30\" MAXLENGTH=\"255\" TABINDEX=\"8\">    </TD>  </TR>  <TR>    <TD></TD>    <TD>      <INPUT TYPE=\"SUBMIT\" NAME=\"submit\" VALUE=\"Vlozit\" TABINDEX=\"9\">    </TD>  </TR>  </FORM></TABLE></DIV> <DIV ALIGN=\"CENTER\"><TABLE>  <FORM ACTION=\"./index.php\" METHOD=\"POST\" ACCEPT-CHARSET=\"ISO-8859-2\" NAME=\"login\">  <TR>    <TD>Meno:</TD>    <TD>      <INPUT TYPE=\"TEXT\" NAME=\"name\" SIZE=\"10\" MAXLENGTH=\"15\" TABINDEX=\"1\">    </TD>  </TR>  <TR>    <TD>Heslo:</TD>    <TD>      <INPUT TYPE=\"PASSWORD\" NAME=\"pass\" SIZE=\"10\" MAXLENGTH=\"15\" TABINDEX=\"2\">    </TD>  </TR>  <TR>    <TD COLSPAN=\"2\"></TD>  </TR>  <TR>    <TD></TD>    <TD>      <INPUT TYPE=\"SUBMIT\" NAME=\"login\" VALUE=\"OK\" TABINDEX=\"3\">    </TD>  </TR>  </FORM></TABLE></DIV>Samozrejme take drobnosti ako kodovanie, nazvy poli a pripadne poslovencenie je na vas a opatovne zalezi od vkusu...

Nakoniec vdychneme nasmu vkladaniu albumov do databazy dusu v podobe hlavneho skriptu \"index.php\", ktory bude doslova \"dievca na vsetko\". (Vyber udajov z tabuliek vsak necham na vas, nech sa aj trochu potrapite a mozno aj naucite...) <?require \"./db.php\"; // vlozenie funkciirequire \"./general.php\";if (($name!=\"\") && ($pass!=\"\")) // najskor sa treba prihlasit  {  db_open();  @$login = mysql_query(\"SELECT * FROM users WHERE name='$name' AND pass='$pass'\"); // vyhladanie mena a hesla v databaze  @$hash = mysql_num_rows($login); // databaza vyhodi n zaznamov, mala by len 1  db_close();  if ($hash==1) // ak je teda iba jeden prihlasili ste sa      {      if ($submit!=\"\") // ak ste uz nieco poslali        {        if ($artist!=\"\") $form = 1; // mali by byt vyplnene nasledujuce polia        if ($album!=\"\") $form = 1;        if ($mb!=\"\") $form = 1;        if ($time!=\"\") $form = 1;        if ($form==1)            {            db_open();            // vlozi zaznam do databazi            @$insert = mysql_query(\"INSERT INTO albums(artist, album, mb, time, cd_number, cd_count, note) VALUES('$artist','$album','$mb','$time','$cd_number','$cd_count','$note')\");            // vymaze potrebne premenne            unset($artist, $album, $mb, $time, $cd_number, $cd_count, $note, $submit);            head(); // a nacita hlavicku            require \"./insert.php\"; // formular            foot(); // paticku            db_close(); // a nakoniec znovu zatvori databazu            }        else            {            head();            require \"./err_ins.php\"; // nezadali ste vsetky nutne udaje            foot();            }        }      else        {        head();        require \"./insert.php\"; // ak ste nic neodoslali, hodi prazdny form        foot();        }      }  else      {      head();      require \"./err_pass.php\"; // zadali ste nespravne heslo      foot();      }  }else  {  head();  require \"./login.php\"; // prihlasovaci formular  foot();  }?> Pozornemu citatelovi urcite neusla malickost. Ako sa vlastne odhlasuje zo systemu? Jednoducho vypnete browser...

Note: Nech mi vsetci zainteresovani a tvorcovia dokonalejsich a dokonalych rieseni prepacia za pripadne chyby. Predchadzajuce riadky su vsak urcene na pouzitie zaciatocnikom, ktorym ucarilo prihlasovanie sa (fuj zavana to skolou, ktora zuri vokol nas), prijemnejsie zadavanie udajov do databazy a samozrejme programujucim systemom copy -> paste.

Pripadne opravy bezpecnostnych dier adresuje autorovi... ;-)ddaemon