Własny mechanizm sesji w PHP

Autor: Tomasz Jędrzejewski
Data publikacji: 11.12.2004, 18:09 | Ostatnia modyfikacja: 06.11.2006, 18:29

ArtykuÅ‚ ten pokazuje, jak od zera zbudować wÅ‚asny system sesji, nie majÄ…cy nic wspólnego z sesjami tradycyjnie dostÄ™pnymi w PHP.



Nowa, poprawiona i bardziej aktualna wersja tego artykułu znajduje się tutaj (format PDF, 190 kb).

Co jakiÅ› czas na forum pojawiaÅ‚y siÄ™ problemy z sesjami PHP. I zawsze w takim przypadku doradzaÅ‚em stworzenie wÅ‚asnego mechanizmu, gdyż wedÅ‚ug mnie, ten dostÄ™pny domyÅ›lnie najlepszy nie jest, czego dowodem jest sama ilość pytaÅ„. Jednak z wÅ‚asnego doÅ›wiadczenia wiem, iż zadanie stworzenia wÅ‚asnego odpowiednika nie należy do Å‚atwych nawet dla osób znajÄ…cych siÄ™ na rzeczy, a co dopiero dla poczÄ…tkujÄ…cych! Dlatego postanowiÅ‚em wyjść im naprzeciw i tak oto narodziÅ‚ siÄ™ ten tekst.

Plany

Sesja w naszym rozumieniu to mechanizm przekazywania danych pomiÄ™dzy wywoÅ‚aniami strony wychodzÄ…cymi od jednego komputera w obrÄ™bie tego samego serwisu. Za jej pomocÄ… tworzone sÄ… rozmaite rzeczy: od koszyków internetowych (dziÄ™ki sesji towary nie "gubiÄ… siÄ™", gdy internauta zmieni podstronÄ™), po systemy autoryzacji i logowania (phpBB, InvisionBoard i wiele innych). My zajmiemy siÄ™ wykorzystaniem sesji do tego ostatniego zadania. Jednak, jak wspomniaÅ‚em wyżej, nie bÄ™dziemy korzystać z tego, co nam podsunÄ™li twórcy PHP. My pójdziemy dalej i stworzymy wszystko od zera. Da to nam peÅ‚nÄ… kontrolÄ™ nad caÅ‚ym mechanizmem, a także możliwość jego rozbudowy o kolejne elementy, wraz z ich obsÅ‚ugÄ… w samym systemie sesji.

SzczegóÅ‚owe dane sesji bÄ™dÄ… trzymane w bazie, miÄ™dzy stronami przekazywany bÄ™dzie 32-znakowy identyfikator sesji. Jego znajomość umożliwi nam zaÅ‚adowanie caÅ‚ej reszty. OczywiÅ›cie pod pewnymi warunkami. Aby upewnić siÄ™, że dane sÄ… pobierane od wÅ‚aÅ›ciwej osoby, musimy przeprowadzić rozmaite testy. U nas bÄ™dzie to tylko jeden - test adresów IP. Jeżeli adres IP zapisany w sesji bÄ™dzie identyczny z tym, który podaje nam serwer, sesjÄ™ można uznać za prawdziwÄ….

Stare sesje musimy usuwać, dlatego bÄ™dÄ… one zawierać pole z czasem ostatniej aktywnoÅ›ci. PrzestarzaÅ‚e po prostu zostanÄ… prÄ™dzej, czy później skasowane, a w razie potrzeby na ich miejscu stworzy siÄ™ nowe.

Jako że nasz mechanizm posÅ‚uży do autoryzacji, musimy wziąć pod uwagÄ™ także roboty wyszukiwarek internetowych. Wiadomo, że nie mogÄ… one przeglÄ…dać strony na równych zasadach z ludźmi, bÄ™dÄ… wiÄ™c dla nich tworzone pseudo-sesje, nie rejestrowane w bazie danych. Taka pseudo-sesja wyklucza caÅ‚kowicie możliwość logowania siÄ™, stÄ…d też roboty nie dotrÄ… do zasobów, które z jakiÅ› przyczyn chcemy chronić.

System przewiduje tylko dwa predefiniowane typy internautów: goÅ›ci oraz użytkowników (zalogowani). Część zasobów bÄ™dzie dostÄ™pna dla wszystkich, część tylko dla zalogowanych użytkowników. W rzeczywistoÅ›ci stosuje siÄ™ o wiele bardziej rozbudowane systemy autoryzacji i przyznawania uprawnieÅ„, jednak jest to temat na innÄ… bajkÄ™. Próba jego opisania tutaj skoÅ„czyÅ‚aby siÄ™ rozrostem tekstu do niemiÅ‚osiernych rozmiarów.

Do góry

Baza danych

System podany poniżej wykorzystuje bazę danych MySQL, stąd też potrzebnych nam będzie parę tabelek. Oto ich kod:

CREATE TABLE `sessions` (
   `session_id` varchar(32) NOT NULL DEFAULT '',
   `session_user` int(8) NOT NULL DEFAULT '0',
   `session_ip` varchar(15) NOT NULL DEFAULT '',
   `session_browser` varchar(128) NOT NULL DEFAULT '',
   `session_time` int(11) NOT NULL DEFAULT '0',
   PRIMARY KEY (`session_id`)
) TYPE=HEAP;
 
CREATE TABLE `users` (
   `user_id` int(10) NOT NULL AUTO_INCREMENT,
   `user_name` varchar(32) NOT NULL DEFAULT '',
   `user_password` varchar(32) NOT NULL DEFAULT '',
   PRIMARY KEY (`user_id`)
);
 
INSERT INTO `users` VALUES (1, 'luser', MD5('ppp'));

W tabeli sessions znajdują się dwa pola przenoszące jakieś dane o użytkowniku strony. Nie są one konieczne mechanizmowi sesji do działania, stąd też możemy je wykorzystać wedle upodobań. session_user przechowuje ID zalogowanego użytkownika. Jeśli sesja należy do gościa, znajdzie się tu wartość "0". Natomiast session_browser może posłużyć do identyfikacji przeglądarki przy wyświetlaniu listy gości w serwisie. Czas (pole session_time) tradycyjnie już zapiszemy w sekundach od 1.1.1970.

Tabela users wygląda tradycyjnie - ot ID, nazwa użytkownika oraz jego hasło tradycyjnie hashowane MD5.

Do góry

Klasa

KlasÄ™ tÄ™ zapiszemy w pliku sessions.php. W niej zawarte bÄ™dÄ… metody sÅ‚użące do Å‚adowania, aktualizacji, tworzenia oraz niszczenia sesji. Jej nagÅ‚ówek wyglÄ…da tak:

<?php
 
   define('SESSION_TIME', 3600);
 
   define('WEBBOT_S', 0);
   define('GUEST_S', 1);
   define('USER_S', 2);
 
   define('ANONYMOUS', 0);
 
   class session{
      var $session_id;
      var $session_user;
      var $session_ip;
      var $session_browser;
      var $session_time;
 
      var $sql_id;
      var $ip;
      var $browser;
      var $type;
 
      var $userdata;

Pierwsze pięć pól sÅ‚uży do gromadzenia danych z sesji. Jeżeli dodamy/usuniemy z bazy jakieÅ› pole, powinniÅ›my także wprowadzić zmianÄ™ wÅ‚aÅ›nie tu. Oprócz tego mamy dodatkowe pięć pól peÅ‚niÄ…ce rozmaite funkcje. W $sql_id zapisany jest ID sesji przepuszczony przez funkcjÄ™ mysql_real_escape_string(), która daje nam pewność, że wszystkie znaki specjalne MySQL'a stanÄ… siÄ™ bezpieczne i nie bÄ™dÄ… rozwalać nam zapytaÅ„ (należy tu uwzglÄ™dnić ustawienia magic_quotes!). $ip i $browser to dane o adresie IP, oraz przeglÄ…darce, z której nadeszÅ‚o żądanie otwarcia strony. $type sÅ‚uży do okreÅ›lania typu sesji, a odpowiednie wartoÅ›ci reprezentujÄ… trzy staÅ‚e podane tuż przed klasÄ…: WEBBOT_S (sesja bota wyszukiwarki), GUEST_S (sesja osoby niezalogowanej) oraz USER_S (sesja osoby zalogowanej). Ostatnim polem jest $userdata bÄ™dÄ…ce tablicÄ…, gdzie zapisujemy wszystkie przydatne informacje o osobie zalogowanej. W naszym przypadku jest to tylko ID i jego nazwa.

Przyszedł teraz czas na zaprezentowanie pierwszej metody. Pobierze ona informacje o tym, skąd nadeszło żądanie otwarcia strony, a także sprawdzi, czy nie gości na naszej stronie przypadkiem bot jednej ze znanych wyszukiwarek. Oto stosowny kod:

      function spy_guest(){
         if(getenv('HTTP_X_FORWARDED_FOR') != ''){
            $this -> ip = (!empty($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : ((!empty($_ENV['REMOTE_ADDR'])) ? $_ENV['REMOTE_ADDR'] : $REMOTE_ADDR );
 
            if(preg_match("/^([0-9]+.[0-9]+.[0-9]+.[0-9]+)/", getenv('HTTP_X_FORWARDED_FOR'), $ip_list)){
               $private_ip = array('/^0./', '/^127.0.0.1/', '/^192.168..*/', '/^172.16..*/', '/^10..*/', '/^224..*/', '/^240..*/');
               $this -> ip = preg_replace($private_ip, $this -> ip, $ip_list[1]);
            }
         }else{
            $this -> ip = (!empty($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : ((!empty($_ENV['REMOTE_ADDR'])) ? $_ENV['REMOTE_ADDR'] : $REMOTE_ADDR );
         }
 
         $this -> browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? $_SERVER['HTTP_USER_AGENT'] : $_ENV['HTTP_USER_AGENT'];
 
         if(preg_match('/(lycos|googlebot|slurp@inktomi|ask jeeves|whatuseek|ia_archiver)/i', $this -> browser)){
            $this -> type = WEBBOT_S;
         }else{
            $this -> type = GUEST_S;
         }
      } // end spy_guest(); 

Jak widać w ostatnich linijkach, "autoryzacja" bota nie jest aż taka skomplikowana. Wystarczy wiedzieć, jak identyfikuje siÄ™ dany robot, a nastÄ™pnie dopisać do wyrażenia, które dokona już reszty.

Kolejna metoda będzie odpowiadać za wykrycie sesji oraz ewentualne wczytanie jej identyfikatora. Kod będzie wyglądał tak:

      function is_session(){
         if(strlen($_COOKIE['my_session_id']) == 32){
            $this -> session_id = $_COOKIE['my_session_id'];
            setcookie('my_session_id', $this->session_id, time() + SESSION_TIME);
            $this -> sql_id = mysql_real_escape_string($this->session_id);
            return 1;
         }
         return 0;
      } // end is_session(); 

Teraz opowiem, jak taki ID sesji wyglÄ…da. Otóż posÅ‚uży nam za niego połączenie aktualnego czasu oraz adresu IP goÅ›cia przepuszczone najpierw przez funkcjÄ™ uniqid(), a nastÄ™pnie przez md5() - każdy identyfikator bÄ™dzie siÄ™ wiÄ™c skÅ‚adaÅ‚ z 32 znaków i to nam może posÅ‚użyć do sprawdzenia, czy takowy jest już ustawiony.

Jeżeli wykryta zostanie sesja, skrypt załaduje do pamięci jej ID, a także przedłuży ważność ciastka.

Gdy już wykryjemy, czy sesja istnieje, czy nie, warto zaÅ‚adować jej dane do pamiÄ™ci oraz dokonać niezbÄ™dnych kontroli. PosÅ‚uży nam do tego metoda load_session(). Zwróci ona 1, gdy nie wystÄ…piÄ… żadne błędy podczas kontroli i Å‚adowania sesji.

      function load_session(){
         $r = mysql_query('SELECT s.*, u.*
                  FROM sessions s LEFT JOIN users u ON (s.session_user <> 0 AND s.session_user = u.user_id)
                  WHERE s.session_id = ''.$this -> sql_id.'' AND s.session_time > '.(time() - 3600));
         if($row = mysql_fetch_row($r)){
            $this -> session_id = $row[0];
            $this -> session_user = $row[1];
            $this -> session_ip = $row[2];
            $this -> session_browser = $row[3];
            $this -> session_time = $row[4];
 
            if($this -> session_user != ANONYMOUS){
               $this -> type = USER_S;
               $this -> userdata['ID'] = $row[5];
               $this -> userdata['NAME'] = $row[6];
            }else{
               $this -> type = GUEST_S;
            }
 
            if($this -> session_browser == $this -> browser && $this -> session_ip == $this -> ip){
               mysql_query('UPDATE sessions SET session_time = ''.time().'' WHERE session_id = ''.$this->sql_id.''');
               return 1;
            }
         }
         $this -> type = GUEST_S;
         return 0;
      } // end load_session(); 

Wypada mi omówić zapytanie użyte do pobrania danych, gdyż zapewne wiele osób nie zna użytej w nim konstrukcji. DziÄ™ki użyciu przeze mnie konstrukcji LEFT JOIN tabela ON warunek mogÄ™ dołączyć do zbioru wyników informacje o zalogowanym czÅ‚owieku, ale tylko wtedy, gdy sesja należy do kogoÅ› takiego! Tak wiÄ™c jeÅ›li w polu session_user znajdzie siÄ™ 0, rekord dotyczÄ…cy użytkownika nie zostanie dołączony do wyniku, gdzie znajdÄ… siÄ™ tylko dane sesji. W przeciwnym wypadku w jednym elemencie wyniku bÄ™dziemy mieli zarówno sesjÄ™, jak i użytkownika. Tym samym skrypt wykona zawsze tylko jedno zapytanie, zamiast dwóch w przypadku koniecznoÅ›ci zaÅ‚adowania dodatkowych informacji.

Jako że starych sesji nie usuwamy przy każdym żądaniu wygenerowania strony (byłoby to zbyt czasochłonne, w końcu jak często się taka sesja trafia?), musimy dołożyć do naszego zapytania odpowiednią blokadę: s.session_time > '.(time() - 3600).

Czasem się zdarzy, że sesję trzeba będzie usunąć. Posłuży nam do tego ta oto metoda:

      function delete_session(){
         mysql_query('DELETE FROM sessions WHERE session_id=''.$this->sql_id.''');
         setcookie('my_session_id', '', 0);
      } // end delete_session(); 

Ustawiam czas ciastka na zero, co w praktyce oznacza jego zniszczenie, gdyż 1.1.1970 minął daaaaaaaaaawno temu.

Kolejne trzy metody bÄ™dÄ… tworzyÅ‚y różne rodzaje sesji. Najpierw zaprezentujÄ™ kod dwóch z nich: do sesji botów, oraz sesji goÅ›ci, gdyż nie wymagajÄ… one specjalnego omówienia.

      function bot_session(){
         $this -> session_id = '';
         $this -> session_user = 0;
         $this -> session_ip = $this -> ip;
         $this -> session_browser = $this -> browser;
         $this -> session_time = 0;
         $this -> userdata = array('ID' => 0, 'NAME' => '');
      } // end bot_session();

      function guest_session(){
         $this -> session_id = md5(uniqid($this->ip.time()));
         $this -> session_user = 0;
         $this -> session_ip = $this -> ip;
         $this -> session_browser = $this -> browser;
         $this -> type = GUEST_S;
         setcookie('my_session_id', $this->session_id, time()+SESSION_TIME);
         mysql_query('INSERT INTO sessions VALUES(''.$this->session_id.'', '0', ''.$this->ip.'', ''.mysql_real_escape_string($this->browser).'', ''.time().'')');
      } // end guest_session();

Kod ten w praktyce tylko wypełnia pola klasy predefiniowanymi danymi, a w przypadku gości dodatkowo dokonuje ustawienia ciastka i zrobienia wpisu w bazie. Ponadto w linijce pierwszej metody guest_session() można zobaczyć, jak wygląda w praktyce generowanie ID sesji.

Dlaczego zdecydowałem się opisać osobno trzecią metodę, user_session()? Ponieważ nie będzie można tak po prostu stworzyć sobie tego rodzaju sesji. Tu znajdą się wszystkie mechanizmy odpowiedzialne za autoryzację podczas logowania, a sesja zostanie utworzona dopiero wtedy, gdy będą one prawdziwe! Z resztą... proszę zobaczyć:

      function user_session(){
         $this -> garbage_collector();
 
         $r = mysql_query('SELECT user_id FROM users WHERE user_name = ''.mysql_real_escape_string($_POST['login']).'' and user_password = ''.md5($_POST['password']).''');
         if($id = mysql_fetch_row($r)){
            if(strlen($this->session_id) == 32){
               mysql_query('UPDATE sessions SET session_user = '.$id[0].', session_time = ''.time().'' WHERE session_id = ''.$this->session_id.''');
               if(mysql_affected_rows() == 1){
                  setcookie('my_session_id', $this->session_id, time()+SESSION_TIME);
               }
            }else{
               $this -> session_id = md5(uniqid($this->ip.time()));
               setcookie('my_session_id', $this->session_id, time()+SESSION_TIME);
               mysql_query('INSERT INTO sessions VALUES(''.$this->session_id.'', ''.$id[0].'', ''.$this->ip.'', ''.mysql_real_escape_string($this->browser).'', ''.time().'')');
            }
            return 1;
         }
         return 0;
      } // end user_session(); 

Dopiero tutaj uruchamiamy metodÄ™ garbage_collector() usuwajÄ…cÄ… stare sesje. Prawdziwość danych sprawdzamy jednym zapytaniem - jeÅ›li zwróci ono jakiÅ› rekord, dane sÄ… prawdziwe i można:

Ostatnia metoda ładnie posprząta po nieużywanych sesjach:

      function garbage_collector(){
         mysql_query('DELETE FROM sessions WHERE session_time < '.(time() - SESSION_TIME));
      } // end garbage_collector();
   }
?>

Teraz maÅ‚a wskazówka dla osób pragnÄ…cych napisać coÅ› w rodzaju "Ostatniej wizyty zalogowanego użytkownika na stronie". Robi siÄ™ to w ten sposób: do tabeli z użytkownikami dodaje siÄ™ pole w stylu user_lastvisit, natomiast w ww. metodzie przed zapytaniem DELETE dodaje siÄ™ jeszcze jedno, wyglÄ…dajÄ…ce mniej wiÄ™cej tak:

UPDATE users, sessions SET user_lastvisit = sessions.session_time WHERE sessions.session_time < '.(time() - SESSION_TIME) 

I po sprawie! W niektórych bazach można to zapytanie przerzucić do triggerów, oszczÄ™dzajÄ…c tym samym kod PHP :).

Do góry

Składamy wszystko do kupy

Chwila, chwila! Przecież nasz kod w takiej postaci jest praktycznie bezużyteczny! Trzeba go jeszcze poskładać w całość. Kod dokonujący autoryzacji znajdzie się w pliku auth.php. Zdefiniowałem tu jedną funkcję - do_auth(), jednak jest ona potrzebna tylko mechanizmowi i nie musisz jej znać. Stworzyłem ją, gdyż zawarta w nim część kodu powtarzała się trzy razy w mechanizmie i po prostu zostawienie tego w wersji pierwotnej zagmatwałoby kod. A tak wiadomo, że jak jest do_auth(), to tu nastąpi autoryzacja danych z formularza do logowania i ewentualne wyświetlenie błędu.

<?php
   
   function do_auth(){
      global $session;
      if($_GET['auth'] == 'login'){
         if(!$session -> user_session()){
            error('Nieprawidłowy login i/lub hasło');
            die();
         }else{
            header('Location: index.php');
            die();
         }
      }
   } // end do_auth(); 

Pierwszym krokiem robionym przez mechanizm jest stworzenie obiektu klasy session oraz obsÅ‚uga sesji botów wyszukiwarek:

   $session = new session;
   $session -> spy_guest();
   
   if($session -> type == WEBBOT_S){
      if(defined('LOGIN_REQUIRED')){
         die('Access denied');
      }
      $session -> bot_session();

Gdy mamy do czynienia ze zwyczajnÄ… sesjÄ…, możemy spróbować zaÅ‚adować jej dane. OczywiÅ›cie boty nie majÄ… dostÄ™pu do stron, do których wymaga siÄ™ logowania, co widać powyżej.

   }elseif($session -> is_session()){   
      if($session -> load_session()){
         do_auth();
 
         if(defined('LOGIN_REQUIRED')){
            if($session -> type != USER_S){
               form_request();
               die();
            }
         }
 
         if($_GET['auth'] == 'logout'){
            $session -> delete_session();
            $session -> guest_session();
            header('Location: index.php');
         }

Strona powiadamia mechanizm, że potrzeba na niÄ… logowania poprzez stałą LOGIN_REQUIRED. Gdy jest ona ustawiona, dokonuje siÄ™ sprawdzenie, czy mamy do czynienia z sesjÄ… usera, a jeÅ›li nie - wyÅ›wietlamy delikwentowi formularz. Tu także obsÅ‚ugujemy akcjÄ™ wylogowywania: najpierw kasujemy sesjÄ™, a później tworzymy sesjÄ™ goÅ›cia.

Gdy nie udało się załadować danych sesji, wykonujemy takie akcje:

      }else{
         $session -> session_id = '';
         do_auth();
 
         if(defined('LOGIN_REQUIRED')){
            form_request();
            die();
         }
         $session -> guest_session();
      }

Krótko: to, co powyżej, tyle że bez obsÅ‚ugi wylogowywania i domyÅ›lnym tworzeniem sesji goÅ›cia.

To samo wykonamy też, gdy sesja w ogóle nie istnieje. Wiadomo, że skoro formularz logowania może wyÅ›wietlić siÄ™ bez sesji, również w takim przypadku musimy wziąć pod uwagÄ™ możliwość autoryzacji.

      do_auth();
      
      if(defined('LOGIN_REQUIRED')){
         form_request();
         die();
      }
      $session -> guest_session();
   }
?>

I... to w zasadzie tyle.

Do góry

Testujemy nasze sesje

Do przetestowania naszego majstersztyksu potrzebujemy jeszcze trochÄ™ kodu PHP: zestawu dodatkowych funkcji (połączenie z bazÄ…, wyÅ›wietlanie formularza logowania, oraz błędu, a także prezentacja nagÅ‚ówka w stylu "Witaj goÅ›ciu"/"Witaj, jesteÅ› zalogowany jako XXX"). Oto plik functions.php:

<?php
 
   function form_request(){
echo <<<EOF
<html>
<head>
<title>Zaloguj siÄ™</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2">
</head>
 
<body>
<center>Zaloguj siÄ™</center>
<form method="post" action="index.php?auth=login">
Twój login: <input type="text" name="login"/><br/>
Twoje hasło: <input type="text" name="password"/><br/>
<input type="submit" value="Loguj!"/>
</form>
</body>
</html>
EOF;
   } // end form_request();
   
   function error($komunikat){
echo <<<EOF
<html>
<head>
<title>BÅ‚&#177;d autoryzacji</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2">
</head>
 
<body>
<center>BÅ‚&#177;d</center>
Podczas autoryzacji wyst&#177;pił bł&#177;d: {$komunikat}
</body>
</html>
EOF;
   } // end error();
 
   function db_connect(){
      mysql_connect('localhost', 'root', '');
      mysql_select_db('artykuly');
   } // end db_connect();
 
   function print_header(){
      global $session;
      if($session -> type == GUEST_S){
         echo 'Witaj, go&#182;ciu<br/>';
      }else{
         echo 'Witaj, jeste&#182; zalogowany jako '.$session -> userdata['NAME'].' (<a href="index.php?auth=logout">Wyloguj</a>)<br/>';
      }
   } // end print_header();
 
   function db_close(){
      mysql_close();
   } // end db_close();
 
?>

Całość natomiast przetestujemy na pięciu stronach: INDEX, STRONA1, STRONA2, STRONA3 i STRONA4. Aby wejść na dwie ostatnie, będziemy się musieli zalogować, w przeciwnym razie dostaniemy formularz do logowania, a nie ich zawartość. Na początek plik index.php:

<?php
   require('functions.php');
   
   db_connect();
   
   require('sessions.php');
   require('auth.php');
   
   print_header();
 
   db_close();
?>
Witaj w INDEX
<ul>
   <li><a href="s1.php">Strona 1</a></li>
   <li><a href="s2.php">Strona 2</a></li>
   <li><a href="s3.php">Strona 3 (wymaga autoryzacji)</a></li>
   <li><a href="s4.php">Strona 4 (wymaga autoryzacji)</a></li>
</ul>

s1.php:

<?php
 
   require('functions.php');
   
   db_connect();
   
   require('sessions.php');
   require('auth.php');
   
   print_header();
 
   db_close();
?>
Witaj w STRONA 1
<ul>
   <li><a href="index.php">INDEX</a></li>
   <li><a href="s2.php">Strona 2</a></li>
   <li><a href="s3.php">Strona 3 (wymaga autoryzacji)</a></li>
   <li><a href="s4.php">Strona 4 (wymaga autoryzacji)</a></li>
</ul>

s2.php:

<?php
 
   require('functions.php');
   
   db_connect();
   
   require('sessions.php');
   require('auth.php');
   
   print_header();
 
   db_close();
?>
Witaj w STRONA 2
<ul>
   <li><a href="index.php">INDEX</a></li>
   <li><a href="s1.php">Strona 1</a></li>
   <li><a href="s3.php">Strona 3 (wymaga autoryzacji)</a></li>
   <li><a href="s4.php">Strona 4 (wymaga autoryzacji)</a></li>
</ul>

s3.php:

<?php
 
   define('LOGIN_REQUIRED', 1);
 
   require('functions.php');
   
   db_connect();
   
   require('sessions.php');
   require('auth.php');
   
   print_header();
 
   db_close();
?>
Witaj w STRONA 3
<ul>
   <li><a href="index.php">INDEX</a></li>
   <li><a href="s1.php">Strona 1</a></li>
   <li><a href="s2.php">Strona 2</a></li>
   <li><a href="s4.php">Strona 4 (wymaga autoryzacji)</a></li>
</ul>

s4.php:

<?php
 
   define('LOGIN_REQUIRED', 1);
 
   require('functions.php');
   
   db_connect();
   
   require('sessions.php');
   require('auth.php');
   
   print_header();
 
   db_close();
?>
Witaj w STRONA 4
<ul>
   <li><a href="index.php">INDEX</a></li>
   <li><a href="s1.php">Strona 1</a></li>
   <li><a href="s2.php">Strona 2</a></li>
   <li><a href="s3.php">Strona 3 (wymaga autoryzacji)</a></li>
</ul>

Przypominam, że aby wymusić konieczność zalogowania siÄ™ na strony 3 i 4, na samym poczÄ…tku plików do ich obsÅ‚ugi zdefiniowaÅ‚em stałą LOGIN_REQUIRED.

Gratulacje, możesz teraz uruchomić skrypt i przetestować go! W bazie jest już zdefiniowany przykładowy użytkownik: "luser", a jego hasło to "ppp".

Do góry

Co dalej?

Sesje i autoryzacja to rozlegÅ‚y temat. Gdyby opisać go dokÅ‚adnie w tym artykule, prawdopodobnie nie starczyÅ‚oby na to miejsca w bazie :). Ponadto, zazwyczaj w tym wypadku najlepiej jest stworzyć system stosowny do naszych potrzeb. Potrzebujemy grup? Dodajemy grupy. A może każdemu z użytkowników bÄ™dzie można osobno definiować uprawnienia? Również nic trudnego. Wystarczy tylko chcieć.

Specjalnie nie rozbudowaÅ‚em powyższego skryptu do rozmiarów i możliwoÅ›ci systemów znanych z phpBB, czy InvisionBoard, byÅ› mógÅ‚ to uczynić sam, w ramach praktyki. Jednak mogÄ™ Å›miaÅ‚o przypuszczać, że niezbyt bÄ™dziesz chciaÅ‚ zgłębiać tajniki kodu ww. systemów, by znaleźć coÅ› interesujÄ…cego. Dlatego też co ciekawsze pomysÅ‚y opisaÅ‚em poniżej.

Do góry

Zakończenie
Mam nadzieję, iż artykuł ten rozjaśnił wszystkie sprawy związane z konstruowaniem własnych systemów sesji oraz pokazał metodę, jak to w ogóle działa. Pytania - jak zawsze, proszę kierować na forum Webcity :).

Autor: Tomasz "Zyx" Jędrzejewski, www.zyxist.com

Do góry

Waszym zdaniem:

Nikt jeszcze nie dodał swojego komentarza. Możesz być pierwszy!


Twoim zdaniem:

Reklama

banner

Partnerzy

CityDesign.pl
phpSolutions