home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 December / PCWorld_2003-12_cd.bin / Novinky / Interval / clanek07.htm < prev    next >
Encoding:
Extensible Markup Language  |  2003-11-04  |  33.9 KB  |  499 lines

  1. <?xml version='1.0' encoding='windows-1250'?>
  2. <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
  3. <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='cs' lang='cs'>
  4. <head>
  5. <meta http-equiv='Content-Type' content='text/html; charset=windows-1250' />
  6. <meta http-equiv='Content-language' content='cs' />
  7. <meta http-equiv='Cache-control' content='no-cache' />
  8. <meta http-equiv='Pragma' content='no-cache' />
  9. <meta http-equiv='Expires' content='0' />
  10. <meta name='robots' content='index, follow' />
  11. <meta name='description' content='Interval.cz - Internetov² magazφn o webdesignu, v²voji webov²ch aplikacφ a e-komerci. VÜe podstatnΘ o technologiφch XHTML, HTML, CSS, DHTML, JavaScript, XML, .NET, ASP, PHP, Java, J2ME, SQL, WAP...' />
  12. <meta name='keywords' content='Interval' />
  13. <meta http-equiv='imagetoolbar' content='no' />
  14. <meta http-equiv='MSThemeCompatible' content='no' />
  15. <meta name='MSSmartTagsPreventParsing' content='true' />
  16. <title>Interval.cz - denn∞ o tvorb∞ webu a e-komerci</title>
  17. <style media='all' type='text/css'>
  18. @import '__services/styles/interval_articles.css';
  19. </style>
  20. </head>
  21. <body class='interval interval-articles'>
  22. <div id='page-header'><div id='interval-logo'><h1 title='Interval.cz - denn∞ o tvorb∞ webu a e-komerci (logo & index link)'><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz'>Interval.cz<span></span></a></h1></div><div id='advertising-page-header'></div><div class='page-maker'> </div></div>
  23. <div id='page-topmenu'><h2 class='textversion'>Navigace</h2><div id='page-mainmenu'><h3 class='textversion'>Hlavnφ menu</h3><ul><li class='first selected'><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz'>Titulnφ strana</a></li><li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz?idcategory=14'>Webdesign</a></li><li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz?idcategory=15'>V²voj aplikacφ</a></li><li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz?idcategory=18'>E-komerce</a></li><li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz?idcategory=17'>Nßstroje</a></li><li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz?idcategory=16'>Magazφn</a></li><li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://diskuse.interval.cz'>Diskusnφ f≤rum</a></li><li class='right'><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.inshop.cz'>Knihkupectvφ</a></li></ul></div><div id='page-mainmenu-maker'> </div></div>
  24. <div id='page-body'><div id='page-left'><div id='article'>
  25.  
  26.  
  27.  
  28. <h2>Autorizßcia v PHP s MySQL</h2>
  29. <p id='prepend'>Vytvori¥ bezpeΦn· autorizßciu, Φi₧e prφstup na strßnky pod u₧φvate╛sk²m menom a heslom, je ne╛ahkß ·loha. Ako oÜetri¥ neoprßvnenΘ prihlßsenie pomocou PHP so sessions v kombinßcii s databßzou MySQL si preΦφtate v tomto Φlßnku.</p>
  30.  
  31.  
  32. <p>Ako teoretick² ·vod posl·₧i Φlßnok <a href='http://interval.cz/clanek.asp?article=1408' title='R∙₧iΦka, Pavel: BezpeΦnost p°edevÜφm û cross-site skripting a session-stealing'>BezpeΦnost p°edevÜφm - cross-site skripting a session-stealing</a>, ktor² varuje pred mo₧n²mi chybami pri pφsanφ takΘhoto skriptu. Vychßdzajme z obvyklej situßcie, kde mßme u₧φvate╛ov systΘmu zapφsan²ch napr. v tabu╛ke <strong>uzivatelia</strong>, ktorß obsahuje polo₧ky <strong>uid</strong> (jedineΦnΘ Φφslo u₧φvate╛a), <strong>meno</strong> (prihlasovacie meno) a polo₧ku <strong>heslo</strong>, kde budeme uchovßva¥ heslo u₧φvate╛a samozrejme zahashovanΘ - v naÜom prφpade algoritmom md5. SQL prφkaz pre vytvorenie tabu╛ky <strong>uzivatelia</strong> bude nasledovn²:</p>
  33.  
  34. <div class='sample'>
  35. CREATE TABLE uzivatelia (
  36. <br />  uid int(10) unsigned NOT NULL auto_increment,
  37. <br />  meno varchar(12) NOT NULL,
  38. <br />  heslo varchar(32) NOT NULL,
  39. <br />  UNIQUE uid (uid)
  40. <br />);
  41. </div>
  42.  
  43. <p>Pre autorizaΦn² skript budeme potrebova¥ eÜte jednu tabu╛ku <strong>autorizacia</strong>, ktorß nßm posl·₧i na evidenciu prihlßsen²ch u₧φvate╛ov, konkrΘtne polo₧ky <strong>sess</strong> (session id), <strong>cas</strong> (Φas prihlßsenia, resp. Φas poslednΘho prφstupu na server) a polo₧ka <strong>user_info</strong> do ktorej si zapφÜeme ·daje o IP adrese u₧φvate╛a pri prihlßsenφ a poΦas celej doby prihlßsenia budeme hodnotu tejto polo₧ky kontrolova¥ s aktußlnym stavom. OpΣ¥ uvßdzam SQL skript pre vytvorenie tabu╛ky <strong>autorizacia</strong>:</p>
  44.  
  45. <div class='sample'>
  46. CREATE TABLE autorizacia (
  47. <br />  aid int(10) unsigned NOT NULL auto_increment,
  48. <br />  sess varchar(32) NOT NULL,
  49. <br />  cas int(10) unsigned DEFAULT '0' NOT NULL,
  50. <br />  user_info varchar(32) NOT NULL,
  51. <br />  UNIQUE aid (aid)
  52. <br />);
  53. </div>
  54.  
  55. <p>Za jednou IP adresou sa m⌠₧e nachßdza¥ nieko╛ko r⌠znych poΦφtaΦov, preto je potrebnΘ skutoΦn· IP adresu zis¥ova¥ sp⌠sobom popφsan²m v hore citovanom Φlßnku:</p>
  56.  
  57. <div class='sample'>
  58. $IPadresa=$REMOTE_ADDR;
  59. <br />$IPadresa.="@".$HTTP_X_FORWARDED_FOR;
  60. <br />$IPadresa.="@".$HTTP_FORWARDED;
  61. <br />$IPadresa.="@".$HTTP_CLIENT_IP;
  62. <br />$IPadresa.="@".$X_HTTP_FORWARDED_FOR;
  63. </div>
  64.  
  65. <p>╚o, ₧ia╛, taktie₧ nerieÜi jedineΦn· identifikßciu poΦφtaΦa, vo vΣΦÜine prφpadoch bude nastavenß len premennß $REMOTE_ADDR, ostatnΘ premennΘ m⌠₧u, ale aj nemusia by¥ nastavenΘ. Proxy posielaj· tieto HTTP hlaviΦky, ale nastavenφm je mo₧nΘ ich zakßza¥. Ja vyu₧φvam na identifikßciu IP adresy funkciu <strong>getVisitorIdentifier</strong>, ktor· nßjdete na strßnke <a href='http://www.cgsa.net/php/identifierShow.php'>identifier PHP functions by Marc Meurrens</a>, Φo je v podstate upravenß vyÜÜie uvedenß identifikßcia s rozlφÜenφm r⌠znych prφpadov nastavenφ (viac napovedia komentßre vo funkcii).</p>
  66. <p>Kontrola IP adresy poΦas doby prihlßsenia m⌠₧e sp⌠sobova¥ problΘmy dial-up u₧φvate╛om, u ktor²ch <strong>sa IP adresa menφ dynamicky pri ka₧dom pripojenφ</strong>. Netreba sa vÜak obßva¥ toho, ₧e prφdeme o dial-up u₧φvate╛ov, treba ich vÜak na t·to situßciu pri prihlasovanφ upozorni¥.</p>
  67. <p>JedineΦnß identifikßcia u₧φvate╛a (resp. poΦφtaΦa) nie je mo₧nß, avÜak k funkcii <strong>getVisitorIdentifier</strong> m⌠₧eme doplni¥ ako dodatoΦn· informßciu typ prehliadaΦa, Φφm zv²Üime presnos¥ identifikßcie. Preddefinovanß premennß <strong>$_SERVER['HTTP_USER_AGENT']</strong> obsahuje re¥azec identifikuj·ci prehliadaΦ, napr. <samp>Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1) Opera 5.12  [en]</samp>.</p>
  68. <p>Na ukß₧ku fungovania autorizßcie si vytvorφme nasledovnΘ s·bory:</p>
  69.  
  70. <div class='list'>
  71. <ul>
  72. <li><strong>index.php</strong> - hlavnß strßnka (cez t·to strßnku vkladßme obsah ∩a╛Üφch strßnok, cez require)</li>
  73. <li><strong>head.php</strong> - hlaviΦka strßnky</li>
  74. <li><strong>foot.php</strong> - pΣta strßnky</li>
  75. <li><strong>settings.php</strong> - nastavenia</li>
  76. <li><strong>login.php</strong> - formulßr pre prihlßsenie</li>
  77. <li><strong>autorizacia.php</strong> - funkcia pre autorizßciu</li>
  78. <li><strong>dalsia1.php, dalsia2.php, dalsia3.php</strong> - s·bory, ktorΘ sa bud· vklada¥ ako obsah strßnky pod╛a zvolenΘho menu</li>
  79. </ul>
  80. </div>
  81.  
  82. <p>S·bor <strong>index.php</strong> obsahuje funkciu <strong>Autorizacia</strong>, ktorß pri ·speÜnom prihlßsenφ vrßti true, inak false a vlo₧φ formulßr pre prihlßsenie u₧φvate╛a. Na zßklade zvolenΘho menu vkladßme obsah strßnok dalsia1.php, dalsia2.php, dalsia3.php. V²stup strßnky posielame do bufferu, preto₧e ∩alej v skripte volßme funkciu <strong>SetCookie</strong>, ktor· je potrebnΘ vola¥ eÜte pred nejak²m v²stupom. Viac o posielanφ v²stupu do bufferu sa m⌠₧ete doΦφta¥ v Φlßnku <a href='http://interval.cz/clanek.asp?article=1063' title='Kocman, Ji°φ: UÜet°ete a₧ 80 % datovΘho p°enosu'>UÜet°ete a₧ 80 % datovΘho p°enosu</a>.</p>
  83.  
  84. <div class='sample'>
  85. <?php
  86. <br />ob_start ();
  87. <br />session_start ();
  88. <br />
  89. <br />require "settings.php";
  90. <br />require "autorizacia.php";
  91. <br />require "head.php";
  92. <br />
  93. <br />if (Autorizacia () == false) {
  94. <br />  require "login.php";
  95. <br />  require "foot.php";
  96. <br />  exit ();
  97. <br />  }
  98. <br />
  99. <br />switch ($_GET["menu"]){
  100. <br />  case "dalsia2":
  101. <br />  case "dalsia3":
  102. <br />    require $_GET["menu"].".php";
  103. <br />    break;
  104. <br />  default:
  105. <br />    require "dalsia1.php";
  106. <br />    break;
  107. <br />  }
  108. <br />
  109. <br />require "foot.php";
  110. <br />ob_end_flush ();
  111. <br />?>
  112. </div>
  113.  
  114. <p>S·bor <strong>head.php</strong> obsahuje pripojenie k databßze a menu s odkazmi na ∩alÜie strßnky <samp><a href="index.php?menu=dalsia1<strong><?php echo (SID?"&amp;".SID:"");?></strong>">Dalsia 1</a></samp>, teda ak je to potrebnΘ, doplnφme session id do odkazov (session.use_trans_sid = 0). Ak je to mo₧nΘ, pou₧ite perzistentnΘ spojenie.</p>
  115. <p>S·bor <strong>foot.php</strong> uzatvßra HTML obsah strßnky a spojenie s databßzou. S·bor <strong>settins.php</strong> obsahuje nastavenia k autorizßcii, v²znam je zrejm² z komentßrov.</p>
  116.  
  117. <div class='sample'>
  118. <?php
  119. <br /><span class='comment'>// debug mode</span>
  120. <br />define ("MK_DEBUG", true);
  121. <br />
  122. <br /><span class='comment'>// typ prihlasenia (0=select, 1=input)</span>
  123. <br />define ("AUTH_TYPE", 1);
  124. <br />
  125. <br /><span class='comment'>// timeout autoodhlasenia (v sekundach)</span>
  126. <br />define ("AUTH_TIMEOUT", 60 * 60);
  127. <br />
  128. <br /><span class='comment'>// ci bude spravcovske heslo platit pre vsetkych</span>
  129. <br />define ("AUTH_USEADMINPASSWD", false);
  130. <br />
  131. <br /><span class='comment'>// ak bude prazdna tabulka uzivatelia, automaticky sa vytvori user AUTH_ADMINUSERNAME, ktory bude povazovany za spravcu (uid=1)</span>
  132. <br />define ("AUTH_ADMINUSERNAME", "[sprßvca]");
  133. <br />
  134. <br /><span class='comment'>// heslo pre automaticky vytvoreneho spravcu (md5)</span>
  135. <br />define ("AUTH_ADMINPASSWD", "21232f297a57a5a743894a0e4a801fc3");
  136. <br />
  137. <br /><span class='comment'>// platnost cookie (10000 dnφ)</span>
  138. <br />define ("AUTH_EXPIRECOOKIE", 60*60*24*(10000));
  139. <br />?>
  140. </div>
  141.  
  142. <p>S·bor <strong>login.php</strong> obsahuje formulßr pre prihlßsenie u₧φvate╛a. Na zßklade konÜtanty <strong>AUTH_TYPE</strong> generujeme HTML formulßr s input alebo option prvkami pre zadanie u₧φvate╛skΘho mena. Ak tabu╛ka <strong>uzivatelia</strong> neobsahuje ₧iadny zßznam, bude vytvoren² u₧φvate╛ <strong>AUTH_ADMINUSERNAME</strong> s heslom <strong>AUTH_ADMINPASSWD</strong>. Premennß <strong>$username</strong>, zφskanß cez <samp>$username = <strong>$_POST</strong>["username"] ? <strong>$_POST</strong>["username"] : <strong>$_COOKIE</strong>["username"];</samp>, bude obsahova¥ hodnotu naposledy prihlßsenΘho u₧φvate╛a (zistenΘ z cookies), alebo hodnotu aktußlne prihlasovanΘho u₧φvate╛a (napr. pri nesprßvne zadanom hesle). V input prvku sa dosadφ username ako hodnota, pri option prvku bude tßto vo╛ba s parametrom selected. JavaScriptom nastavφme kurzor do potrebnΘho prvku.</p>
  143.  
  144. <div class='sample'>
  145. <strong><?php
  146. <br />$username = $_POST["username"] ? $_POST["username"] : $_COOKIE["username"];
  147. <br />?></strong>
  148. <br /><strong>Autorizßcia u₧φvate╛a</strong>
  149. <br /><form method="post" action="index.php" name="formular">
  150. <br /><input type="hidden" name="PHPSESSID" value="<strong><?php echo session_id ()?></strong>" />
  151. <br />U₧φvate╛ : <strong><?php echo HTMLlogin ($username)?></strong><br />
  152. <br />Heslo : <input type="password" name="passwd" />
  153. <br /><input type="submit" value="Prihlßsenie" />
  154. <br /></form>
  155. <br /><script type="text/javascript">
  156. <br />function Focuzz () {
  157. <br />  <strong><?php
  158. <br />  if (empty($username))
  159. <br />    echo "document.formular.username.focus ()\n";
  160. <br />  else
  161. <br />    echo "document.formular.passwd.focus ()\n";
  162. <br />  ?></strong>
  163. <br />  }
  164. <br />window.onload = Focuzz
  165. <br /></script>
  166. </div>
  167.  
  168. <p>Funkcia generuj·ca formulßrov² prvok pre zadanie u₧φvate╛skΘho mena, pod╛a konÜtanty <strong>AUTH_TYPE</strong>:</p>
  169.  
  170. <div class='sample'>
  171. <?php
  172. <br />function HTMLlogin ($username) {
  173. <br />
  174. <br />  $query = "SELECT * FROM uzivatelia ORDER BY meno";
  175. <br />  $result = mysql_query ($query) or die();
  176. <br />  <span class='comment'>// ak neexistuju uzivatelia, vytvor spravcu systemu s heslom</span>
  177. <br />  if (mysql_num_rows ($result) == 0) {
  178. <br />    $result = mysql_query ("INSERT INTO uzivatelia (meno, heslo) VALUES ('".AUTH_ADMINUSERNAME."', '".AUTH_ADMINPASSWD."')");
  179. <br />    $result = mysql_query ($query) or die();
  180. <br />    }
  181. <br />
  182. <br />  if (AUTH_TYPE == 0){
  183. <br />    $s = "<select name='username'>\n";
  184. <br />    while ($row = mysql_fetch_object ($result)) {
  185. <br />      if ($username == $row->meno)
  186. <br />        $s .= "<option value='$row->meno' selected style='background-color:#ffffff'>$row->meno</option>\n";
  187. <br />      else
  188. <br />        $s .= "<option value='$row->meno' style='background-color:#e0e0ff'>$row->meno</option>\n";
  189. <br />      }
  190. <br />    $s .= "</select>\n";
  191. <br />    }
  192. <br />  else if (AUTH_TYPE == 1) {
  193. <br />    $s = "<input type='text' name='username' value='$username' />\n";
  194. <br />    }
  195. <br />
  196. <br />  return $s;
  197. <br />  }
  198. <br />?>
  199. </div>
  200.  
  201. <p>S·bor <strong>autorizacia.php</strong> obsahuje funkcie pre spracovanie prihlasovacieho formulßra a nßsledne kontrolu session id a zahashovan· hodnotu IP adresy s typom browsera. V ·vode funkcie kontrolujeme, Φi nebolo zvolenΘ odhlßsenie danΘho u₧φvate╛a, ak ßno, funkcia Logout sa postarß o vymazanie zßznamu s t²mto session id z tabu╛ky autorizacia a odstrßni session premennΘ (<strong>session_destroy</strong> by sp⌠sobilo vymazanie session a <strong>session_id</strong> by bolo prßzdne, preto si toto session id ponehßme aj pre ∩alÜie prihlßsenie, niΦ t²m nepokazφme, len odstrßnime jeho premennΘ).</p>
  202.  
  203. <div class='sample'>
  204. function Autorizacia () {
  205. <br />  if ($_GET["menu"] == "logout"){
  206. <br />    Logout ();
  207. <br />    return false;
  208. <br />  }
  209. <br />  ...
  210. <br />  ...
  211. <br />
  212. <br />function Logout () {
  213. <br />  <span class='comment'>// zmaz zaznam so session_id</span>
  214. <br />  $result = mysql_query ("DELETE FROM autorizacia WHERE sess='".session_id ()."'") or die();
  215. <br />  <span class='comment'>// odstran session premenne</span>
  216. <br />  reset ($_SESSION);
  217. <br />  while (list ($key, ) = each ($_SESSION))
  218. <br />    unset($_SESSION[$key]);
  219. <br />  }
  220. </div>
  221.  
  222. <p>V ∩alÜom kroku vyhodnotφme podmienku <samp>isset($_POST["username"]) && isset($_POST["passwd"]) && empty($_SESSION["uid"])</samp>, ktorß nßm pri splnenφ hovorφ o tom, ₧e boli vyplnenΘ vstupnΘ hodnoty a u₧φvate╛ sa prßve prihlasuje (eÜte nie je prihlßsen²), Φo oÜetruje situßciu, ak by bol ihne∩ po prihlßsenφ vyvolan² refresh strßnky. ZadanΘ heslo zahashujeme funkciou md5 <samp>$_POST["passwd"] = md5 ($_POST["passwd"]);</samp>. Ak bude nastavenß konÜtanta <strong>AUTH_USEADMINPASSWD</strong>, sprßvcovskΘ heslo (zßznam s uid=1) bude platnΘ pre vÜek²ch ostatn²ch u₧φvate╛ov. Zφskanie sprßvcovskΘho hesla:</p>
  223.  
  224. <div class='sample'>
  225. if (AUTH_USEADMINPASSWD) {
  226. <br />  <span class='comment'>// zisti spravcovske heslo</span>
  227. <br />  $result = mysql_query ("SELECT heslo FROM uzivatelia WHERE uid='1'") or die();
  228. <br />  $row = mysql_fetch_object($result);
  229. <br />  $admin_passwd = $row->heslo;
  230. <br />  }
  231. </div>
  232.  
  233. <p>Teraz sa pok·sime z tabu╛ky uzivatelia vybra¥ zßznam so zadan²m menom a heslom. OpΣ¥ bereme do ·vahy aj nastavenie konÜtanty  <strong>AUTH_USEADMINPASSWD</strong>:</p>
  234.  
  235. <div class='sample'>
  236. <span class='comment'>// vyber uzivatela "username" s heslom "passwd"</span>
  237. <br />$result = mysql_query ("SELECT * FROM uzivatelia WHERE meno='".$_POST["username"]."' AND heslo='".$_POST["passwd"]."'") or die();
  238. <br />
  239. <br />if (AUTH_USEADMINPASSWD && !mysql_num_rows ($result)) {
  240. <br />  <span class='comment'>// zaznam neexistuje, kontroluj spravcovske heslo</span>
  241. <br />  if ($admin_passwd == $_POST["passwd"]) {
  242. <br />    <span class='comment'>// heslo je OK - vyber uzivatela "username"</span>
  243. <br />    $result = mysql_query ("SELECT * FROM uzivatelia WHERE meno='".$_POST["username"]."'") or die();
  244. <br />    return AuthInsert ($result);
  245. <br />    }
  246. <br />  }
  247. <br />return AuthInsert ($result);
  248. </div>
  249.  
  250. <p>Funkcia <strong>AuthInsert</strong> sa nßm pri nßjdenφ tohoto zßznamu postarß o pridanie u₧φvate╛a do tabu╛ky autorizacia, kde si pri vlo₧enφ zßznamu zapφÜeme session id, Φas prihlßsenia a zahashovanΘ informßcie o IP adrese a type prehliadaΦa - funkcia <strong>GetUserInfo</strong>. Funkciu function <strong>getVisitorIdentifier</strong> som pridal z u₧ spomφnanej strßnky Marca Meurrensa. Z tabu╛ky autorizacia eÜte vyma₧eme zßznamy, ktor²m vyprÜal Φas AUTH_TIMEOUT od poslednej akcie so serverom. Cez <strong>SetCookie</strong> nastavφme premenn· <strong>$username</strong> na hodnotu prßve prihlßsenΘho u₧φvate╛a, ktor· vyu₧φvame v s·bore <strong>login.php</strong>. Do superglobßlnej premennej $_SESSION vlo₧φme hodnoty, ktorΘ m⌠₧eme naΦφta¥ napr. z tabu╛ky u₧φvatelia a vyu₧φva¥ ich poΦas doby prihlßsenia. Povinnß je hodnota <strong>uid</strong>, ktor· vyu₧φvame v spomφnanej podmienke funkcie Autorizacia <samp>isset($_POST["username"]) && isset($_POST["passwd"]) && empty($_SESSION["uid"])</samp>. Pri ·speÜnom pridanφ zßznamu do tabu╛ky autorizacia vrßti funkcia AuthInsert hodnotu true, inak false - ne·speÜnΘ prihlßsenie. Funkcia <strong>HTMLlogout</strong> v dobe prihlßsenΘho u₧φvate╛a zobrazφ odkaz n odhlßsenie u₧φvate╛a (menu=logout).</p>
  251.  
  252. <div class='sample'>
  253. function AuthInsert ($result) {
  254. <br />  if (mysql_num_rows($result)) {
  255. <br />    $row = mysql_fetch_object ($result);
  256. <br />
  257. <br />    <span class='comment'>// pridaj session_id a cas prihlasenia do tabulky autorizacia</span>
  258. <br />    mysql_query ("INSERT INTO autorizacia (sess, cas, user_info) VALUES ('".session_id ()."', '".time()."', '".GetUserInfo()."')") or die();
  259. <br />    <span class='comment'>// vymaz stare zaznamy</span>
  260. <br />    mysql_query ("DELETE FROM autorizacia WHERE cas < ".(time() - AUTH_TIMEOUT)) or die();
  261. <br />
  262. <br />    setcookie("username", $row->meno, time() + AUTH_EXPIRECOOKIE);
  263. <br />    $_SESSION["uid"] = $row->uid;
  264. <br />    $_SESSION["username"] = $row->meno;
  265. <br />    $_SESSION["ip_full"] = getVisitorIdentifier();
  266. <br />    $_SESSION["browser"] = $_SERVER['HTTP_USER_AGENT'];
  267. <br />
  268. <br />    return HTMLlogout ();
  269. <br />    }
  270. <br />  return false;
  271. <br />  }
  272. <br />
  273. <br />function GetUserInfo () {
  274. <br />  return md5(getVisitorIdentifier().$_SERVER['HTTP_USER_AGENT']);
  275. <br />  }
  276. <br />
  277. <br />function HTMLlogout () {
  278. <br />  if ($_GET["menu"] != "logout")
  279. <br />    echo "<a href='index.php?menu=logout".(SID?"&amp;".SID:"")."'>Odhlßsenie</a>";
  280. <br />  return true;
  281. <br />  }
  282. </div>
  283.  
  284. <p>Ak je u₧φvate╛ prihlßsen², je potrebnΘ prekontrolova¥, Φi sa zßznam s dan²m session id a zahashovanou IP adresou s typom browsera nachßdza v zßznamoch tabu╛ky autorizacia. Pri existencii takΘhoto zßznamu prekontrolujeme, Φi nevyprÜal Φas AUTH_TIMEOUT a nastavφme nov· hodnotu Φasu prφstupu na server. Ak zßznam neexistuje, alebo vyprÜal Φas neΦinnosti poΦas doby prihlßsenia vrßti nßm funkcia Autorizacia hodnotu false (vyma₧· sa tie₧ ostatnΘ zßznamy s vyprÜan²m Φasom a odstrßni sa aktußlne session), inak vrßti true.</p>
  285.  
  286. <div class='sample'>
  287. <span class='comment'>// nebol zadany uzivatel ani heslo</span>
  288. <br /><span class='comment'>// existuje zaznam s takymto session_id ?</span>
  289. <br />$result = mysql_query ("SELECT * FROM autorizacia WHERE sess='".session_id ()."' AND user_info='".GetUserInfo()."'") or die();
  290. <br /><span class='comment'>// ano existuje</span>
  291. <br />if ( mysql_num_rows ($result) ) {
  292. <br />  $row = mysql_fetch_object ($result);
  293. <br />  <span class='comment'>// nevyprsal timeout ?</span>
  294. <br />  if (time() - $row->cas < AUTH_TIMEOUT) {
  295. <br />    <span class='comment'>// update casu</span>
  296. <br />    mysql_query ("UPDATE autorizacia SET cas='".time()."' WHERE aid='".$row->aid."'") or die();
  297. <br />    return HTMLlogout ();
  298. <br />    }
  299. <br />  <span class='comment'>// ano vyprsal</span>
  300. <br />  else {
  301. <br />    mysql_query ("DELETE FROM autorizacia WHERE cas < ".(time() - AUTH_TIMEOUT)) or die();
  302. <br />    session_destroy ();
  303. <br />    }
  304. <br />  }
  305. <br />return false;
  306. </div>
  307.  
  308. <p>Najd⌠le₧itejÜφm bezpeΦnostn²m prvkom autorizßcie bude protokol <strong>https</strong>. Korektne napφsan² skript vyu₧φvaj·ci https musφ obsahova¥ vÜetky odkazy s absol·tnou cestou, k tomu si medzi konÜtanty (settings.php) vlo₧φme konÜtantu definuj·cu absol·tnu cestu <samp>define ("HTTPS_PATH", "https://localhost/autorizacia/");</samp> k s·borom, ktorΘ si ₧elßme ma¥ zabezpeΦenΘ. V downloade zdrojov²ch k≤dov nßjdete tieto odkazy u₧ upravenΘ.</p>
  309. <p>Ukladanie sessions na serveroch obvykle ostßva v prednastavenom adresßri <strong>/tmp</strong>, avÜak k zv²Üeniu bezpeΦnosti je vhodnΘ si session uklada¥ do nami zvolenΘho adresßra, a to jednoduch²m pridanφm funkcie <samp>session_save_path("session/autorizacia/")</samp> eÜte pred volanφm session_start().</p>
  310. <p>Okrem s·borov m⌠₧eme session uklada¥ aj do databßzy, Φo pri sprßvnom nastavenφ prßv k databßze posunie ·rove≥ bezpeΦnosti zas o nieΦo vyÜÜie.  Na ukladanie sessions do databßzy je potrebnß funkcia <strong>session_set_save_handler</strong> plus ∩alÜie nami definovanΘ funkcie k prßci so sessions. Tieto funkcie m⌠₧eme nßjs¥ na internete, napr. na strßnke <a href='>http://www.phpbuilder.com/columns/ying20000602.php3?page=1'>Custom Session Handlers in PHP4</a>. Implementßcia pozostßva z vytvorenia tabu╛ky <strong>sessions</strong>, ktorej Ütrukt·ru nßjdete v s·bore <strong>session_mysql.php</strong>, a vlo₧enia tohto s·boru pred session_start v index.php.</p>
  311.  
  312. <div class='sample'>
  313. <?php
  314. <br />ob_start ();
  315. <br />
  316. <br /><strong>require "session_mysql.php";</strong>
  317. <br />session_start ();
  318. <br />
  319. <br />require "settings.php";
  320. <br />require "autorizacia.php";
  321. <br />require "head.php";
  322. <br />...
  323. <br />...
  324. </div>
  325.  
  326. <p>Pre ukladanie sessions do databßzy je potrebnΘ nastavi¥ direktφvu <strong>session.save_handler = user</strong> v <strong>php.ini</strong>, alebo priamo v naÜich skriptoch funkciou <strong>ini_set("session.save_handler","user")</strong>.</p>
  327. <p>Aby sme zabrßnili vkladaniu generovan²ch hesiel, poistφme strßnku obrßzkom s re¥azcom, ktor² bude potrebnΘ zapφsa¥ pri prihlasovanφ. Obohatφme formulßr v s·bore login.php nasledovn²m k≤dom:</p>
  328.  
  329. <div class='sample'>
  330. Kontroln² re¥azec : 
  331. <br /><span class='comment'><!-- ROZMERY IMG TREBA UPRAVIT PRI ZMENE KONSTANT V ImgRndStr.php --></span>
  332. <br /><img src="imgrndstr.php<?php echo (SID?"?".SID:"")?>" width="27" height="21"> <input type="text" name="str" size="3" />
  333. </div>
  334.  
  335. <p>S·bor <strong>ImgRndStr.php</strong> vytvßra obrßzok s nßhodn²m re¥azcom a taktie₧ tento re¥azec zapφÜe do session. Po zadanφ mena a hesla skontrolujeme, Φi je zadan² a session re¥azec zhodn². Doplnok do funkcie Autorizacia (tuΦnΘ pφsmo):</p>
  336.  
  337. <div class='sample'>
  338. function Autorizacia () {
  339. <br />  if ($_GET["menu"] == "logout"){
  340. <br />    Logout ();
  341. <br />    return false;
  342. <br />    }
  343. <br />
  344. <br />  if (isset($_POST["username"]) && isset($_POST["passwd"]) && empty($_SESSION["uid"])) {
  345. <br />
  346. <br />    <strong>if($_POST["str"]!=$_SESSION["str"])
  347. <br />      return false;
  348. <br />
  349. <br />    unset($_SESSION["str"]);</strong>
  350. <br />...
  351. <br />...
  352. </div>
  353.  
  354. <p>Aby bolo aj pre poΦφtaΦ nßroΦnΘ rozpozna¥, ak² znak sa v obrßzku nachßdza, zvolil som pri generovanφ re¥azca met≤du nßhodnΘho vypos·vania znakov v horizontßlnom aj vertikßlnom smere, samozrejme v hraniciach rozpoznania Φlovekom. Pre zobrazenie znakov vyu₧φvam zßkladn² font 5 (mo₧nΘ pou₧i¥ 1 a₧ 5, priΦom vΣΦÜie Φφslo udßva vΣΦÜφ font), ktor² je s·Φas¥ou grafickej kni₧nice PHP (ak nie je zakompilovanß ako s·Φas¥ PHP treba v php.ini navoli¥: extension=php_gd(2).dll (.so pre linux), alebo v ·vode skriptu naΦφta¥ cez funkciu <strong>dl</strong>). Ke∩₧e sa jednß o neproporcionßlne pφsmo, v ·vode si zistφme v²Üku a Üφrku znaku. ╧alej vytvorφme obrßzok s rozmermi pod╛a poΦtu znakov a rozsahu horizontßlnej premennej, ktorß urΦuje ako ve╛mi bud· znaky äskßka¥ô v horizontßlnom smere. NiektorΘ konÜtanty (farby, font, dσ₧ku re¥azca, typ nßhodn²ch znakov a horizontßlnu premenn·) je mo₧nΘ jednoducho zmeni¥ na zaΦiatku skriptu ImgRndStr.php. Znak nula, ve╛kΘ a malΘ pφsmeno O sa v generovanom re¥azci nevyskytuje (nahradenΘ cez funkciu strtr), preto₧e s· navzßjom dos¥ podobnΘ. Nßhodn² posun vo vertikßlnom smere je v rozsahu jednΘho pixelu. Taktie₧ je mo₧nΘ ako podklad vlo₧i¥ obrßzok, ktor² by eÜte viac skomplikoval dek≤dovanie re¥azca z obrßzku.</p>
  355. <p>Funkciu <strong>ImageColorAllocate</strong> som rozÜφril o zadßvanie farieb typu #rrggbb, ktorej nßzov je ImageColorAllocateHex.</p>
  356.  
  357. <div class='sample'>
  358. function ImageColorAllocateHex ($im, $rgb) {
  359. <br />  $rgb = eregi_replace("#","",$rgb);
  360. <br />
  361. <br />  $r = hexdec (substr ($rgb,0,2));
  362. <br />  $g = hexdec (substr ($rgb,2,2));
  363. <br />  $b = hexdec (substr ($rgb,4,2));
  364. <br />
  365. <br />  return ImageColorAllocate ($im, $r, $g, $b);
  366. <br />  }
  367. </div>
  368.  
  369. <p>A pre ·plnos¥ k≤d s·boru imgrndstr.php (pri ukladanφ sessions do databßzy vlo₧i¥ pred session_start riadok <samp>require "session_mysql.php";</samp> - ak preferujete t·to mo₧nos¥, je vhodnΘ upravi¥ skript tak, aby sme sa k databßze pripßjali len raz):</p>
  370.  
  371. <div class='sample'>
  372. <?php
  373. <br /><span class='comment'>###########################
  374. <br />// require "session_mysql.php";
  375. <br />###########################</span>
  376. <br />
  377. <br />session_start ();
  378. <br />
  379. <br /><span class='comment'>###############################
  380. <br /># konstanty
  381. <br />###############################</span>
  382. <br />$bgcolor = "#cccccc";
  383. <br />$color = "#000000";
  384. <br />$font = 5;
  385. <br />$length = 3;
  386. <br />
  387. <br /><span class='comment'>// 1 = (0..9)</span>
  388. <br /><span class='comment'>// 2 = (0..9, A..Z)</span>
  389. <br /><span class='comment'>// 3 = (0..9, A..Z, a..z)</span>
  390. <br />$type = 2;
  391. <br />
  392. <br /><span class='comment'>// kolko budu znaky "skakat" v horizontalnom smere</span>
  393. <br />$y = 6;
  394. <br />
  395. <br /><span class='comment'>###############################
  396. <br /># samotny skript - generator
  397. <br />###############################</span>
  398. <br />header ("Content-type: image/png");
  399. <br />
  400. <br /><span class='comment'>// inicializacia nahodneho generatora (od verzie PHP 4.2.0 nepotrebna)</span>
  401. <br />srand ((double) microtime() * 1000000);
  402. <br />
  403. <br />$w = ImageFontWidth ($font);
  404. <br />$h = ImageFontHeight ($font);
  405. <br />
  406. <br />$s="";
  407. <br />for($i=0 ; $i<$length ; $i++)
  408. <br />  switch (rand() % $type) {
  409. <br />    case 0: $s.=chr (rand(ord('0'),ord('9'))); break;
  410. <br />    case 1: $s.=chr (rand(ord('A'),ord('Z'))); break;
  411. <br />    case 2: $s.=chr (rand(ord('a'),ord('z'))); break;
  412. <br />    }
  413. <br />$s = strtr ($s,"0Oo","1Aa");
  414. <br />
  415. <br />$im = ImageCreate ($w*$length, $h+$y) or die ("GD error !");
  416. <br />$bgcolor = ImageColorAllocateHex ($im,$bgcolor);
  417. <br />$color = ImageColorAllocateHex ($im,$color);
  418. <br />
  419. <br />$m = rand(1,2);
  420. <br />for($i=0 ; $i<$length ; $i++) {
  421. <br />  if ($i)
  422. <br />    $m = $m>1 ? 0 : rand(-1,0);
  423. <br />  ImageChar ($im, $font, $w*$i+$m, rand() % $y, $s[$i], $color);
  424. <br />  }
  425. <br />
  426. <br />ImagePng ($im);
  427. <br />
  428. <br />$_SESSION["str"] = $s;
  429. </div>
  430.  
  431. <p>Pre maximßlnu bezpeΦnos¥ je mo₧nΘ naviac generova¥ dodatoΦnΘ heslo a to potom zasiela¥ u₧φvate╛om na mail, alebo formou SMS, ale pre be₧nΘ prihlasovanie myslφm tak²to sp⌠sob postaΦφ.</p>
  432. <p><a href='podklady/kubis/653/autorizacia.zip'>S·bory, potrebnΘ k rozbehaniu autorizßcie</a>, s· vßm k dispozφcii.</p>
  433.  
  434.  
  435.  
  436. <div id='article-author'>
  437. <a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/autor.asp?author=51'>KubiÜ, Michal</a> (23.10. 2003)
  438.  
  439. </div>
  440.  
  441.  
  442.  
  443. </div></div>
  444. <div id='page-right'><h2 class='textversion'>Prav² sloupek</h2>
  445. <div id='search'><h3 class='textversion'>Vyhledßvßnφ</h3><form method='get' action='http://interval.cz/search.asp'><div><input type='text' name='hledej' class='text' /><input type='submit' class='submit' value='Najdi!' /></div></form><div><a href='http://interval.cz/search_ex.asp'>RozÜφ°enΘ vyhledßvßnφ</a></div></div>
  446.  
  447.  
  448.  
  449. <div class='page-right-box book'>
  450.     <h3>Kni₧nφ novinka</h3>
  451.     <div class='page-right-box-in'>
  452.         <div class='book-top'>
  453.             <h4><a href='http://interval.cz/redirect/redirect.asp?what=interval_booknews&url=http://interval.inshop.cz/inshop/scripts/detail.asp?ItemID=226'>Hacking bez tajemstvφ: Java a J2EE</a></h4>
  454.         </div>
  455.     </div>
  456.     <div class='image'>
  457.         <a href='http://interval.cz/redirect/redirect.asp?what=interval_booknews&url=http://interval.inshop.cz/inshop/scripts/detail.asp?ItemID=226'><img src='podklady/knihy/image.jpg' alt='obßlka' title='obßlka' /></a>
  458.     </div>
  459.     <div class='book-bottom'>Cena: <span class='book-price-old'>490 KΦ</span> <span class='book-price-new'>411 KΦ</span></div>
  460. </div>
  461.  
  462.  
  463.  
  464. <div class='page-right-box reading'>
  465.     <h3>NejΦten∞jÜφ</h3>
  466.     <div class='page-right-box-in'>
  467.         <ul>
  468. <li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=2751'>NovΘ p°echody - p°ehled IV</a></li>
  469. <li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=2752'>Java a 3D grafika</a></li>
  470. <li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=2694'>Czech.NET Forum - diskusnφ f≤rum v ASP.NET</a></li>
  471. <li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=2767'>Zprßvy z Proffesional Developers Conference (PDC 2003)</a></li>
  472. <li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=2702'>KonfiguraΦnφ soubor v PHP, tentokrßt ve formßtu .ini</a></li>
  473.         </ul>
  474.     </div>
  475. </div>
  476.  
  477.  
  478.  
  479. <div class='page-right-box cauldron'>
  480.     <h3>Diskuznφ kotel</h3>
  481.     <div class='page-right-box-in'>
  482.         <ul>
  483. <li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=2541'>dreamface.net</a><div>184 komentß°∙ </div></li>
  484. <li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=2561'>Internet Explorer 7 se jmenuje MyIE2</a><div>143 komentß°∙ </div></li>
  485. <li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=1328'>XHTML v praxi</a><div>124 komentß°∙ </div></li>
  486. <li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=2714'>Prvnφ Dobr² web v ╚echßch</a><div>87 komentß°∙ </div></li>
  487. <li><a href='http://interval.cz/redirect/redirect.asp?what=interval_offline&url=http://interval.cz/clanek.asp?article=2763'>bone-ju</a><div>72 komentß°∙ </div></li>
  488.         </ul>
  489.     </div>
  490. </div>
  491.  
  492.  
  493.  
  494. <div class='page-right-box emailserv'><h3>Email servis</h3><div class='page-right-box-in'><form action='prihlaseni.asp' method='post'><div class='shell'><input class='text' type='text' name='adresa' /></div><div class='shell'><input class='radio' type='radio' value='1' name='co' checked='checked' />T²dennφ p°ehled Φlßnk∙</div><div class='shell'><input class='radio' type='radio' value='2' name='co' />HELP konference</div><div class='shell'><input class='submit' type='submit' value='P°ihlßsit' /></div></form></div></div>
  495. </div>
  496. <div class='page-maker'> </div><div class='page-maker-white'> </div></div>
  497. <div id='page-foot'><div id='page-foot-menu'><a href='http://interval.cz/reklama.asp'>Inzerce na Interval.cz</a> | <a href='http://interval.cz/redakce.asp'>Redakce Interval.cz</a> | <a href='http://interval.cz/autori.asp'>Hledßme novΘ autory</a></div><div id='issn'>ISSN 1212-8651</div><div id='page-foot-zoner'>© Zoner software, s.r.o., vÜechna prßva vyhrazena, tento server dodr₧uje <a href='http://interval.cz/privacy.asp'>prßvnφ p°edpisy</a>o ochran∞ osobnφch ·daj∙.</div></div>
  498. </body>
  499. </html>