Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Logowanie i sesja
Forum PHP.pl > Forum > Przedszkole
uirapuru
Takie szybkie pytanie, jak ogólnikowo wygląda model logowania i obsługi sesji w Waszych projektach? Czy może jest jakiś uniwersalny dobry sposób robienia tego? Przyznam, że zrobiłem sam, działa, ale nie wiem na ile jest włamoodporne i może znalazłoby sie lepsze rozwiązanie.
wNogachSpisz
Korzystam z frameworka CodeIgniter, tam sesja jest zaimplementowana i dostepna dla kodującego w bardzo przyzwoitym abstrakcyjnym layerze

* szyfrowanie sesji
* flashdata (taki var w sesji ktory znika po kolejnym przeladowniu strony, dobre do obslugi komunikatow)

Nie ukrywam ze szyfrowanie sesji daje duze mozliwosci mozna sie szarpnac na  przechowywaniem w cookie wartosci logged_as=>admin
juz nie trzeba sprawdzac SID'a w bazie czy gdziekolwiek indziej, a to moze szalenie pozytywnie wplynac na wydajnosc ;p i u mnie wplywa ;p
pgrzelka
pokaż kod to powiemy czy skrypt jest bezpieczny
uirapuru
Nie wiem czy będzie chciało się komuś analizować kod, ale podaję jego najważniejsze części. Generalnie wymyśliłem to sobie tak, że wspolpracuja ze soba trzy glowne obiekty (przy czym nie mam zielonego pojecia o programowaniu obiektowym jeszcze, wiec wybaczcie bledy i chetnie poczytam wskazowki)

Sesja() - jest warstwa pomiedzy sesją a skryptem, generalnie settery i gettery, sprawdzanie czy sesja istnieje i czy klient jest zalogowany
Profil() - info o uzytkowniku (nazwiska, zdjecia itp)
User() - haslo, nazwa, mail
Mainframe() - taki niby obiekt, a wlasciwie to plik index odwoluje sie tylko do jego metod a on "rozporządza" akcjami

TabProfiles(), TabUsers() - warstwa pomiedzy skryptem a bazą (potomne klasy Mysql, ktora nawiazuje i konczy polaczenie) - maja metody zawierajace bezposrednie query do bazy, a takze metody ktore mi troche ulatwiaja prace (np. GetProfileIDfromUserID() itd)

No wiec po kolei, bede wklejac kluczowe fragmenty:

plik index.php:

  1. <?php
  2. switch($akcja[1]) {
  3.    case "reg":
  4.        if($_POST["akcja"]=="reg")
  5.        {
  6.            if($mainframe->rejestracja($_POST)) { header("location: /"); }
  7.        }
  8.        else
  9.        {
  10.            header("location: /login");
  11.        }
  12.        break;
  13.    case "login":
  14.        if(isset($_POST["akcja"]) && $_POST["akcja"]=="login") {
  15.            if($mainframe->logowanie($_POST)) { header("location: /"); }
  16.        }
  17.        else
  18.        {
  19.            echo MAIN_HTML_HEAD;
  20.            $form->menu();
  21.            $form->logowanie();
  22.            $form->rejestracja();
  23.        }
  24.        break;
  25.    case "logout":
  26.        $mainframe->wylogowanie();
  27.        header("location: /");
  28.        break;
  29.    case "profil":
  30.        if(!$sesja->get("loggedin"))
  31.        { // jeśli nie zalogowany przekierowuje na strone logowania
  32.            header("location: /login");
  33.            break;
  34.        }
  35.        if(isset($_POST["akcja"]) && $_POST["akcja"]=="profile")
  36.        { // jesli zalogowany i nastapilo wyslanie formularza wykonuje akcje
  37.            $mainframe->profil_edit($_POST,$_FILES);
  38.            header("location: /profil");
  39.        }
  40.        else
  41.        { // w innym wypadku pokazuje jedynie formularz do edycji profilu
  42.            echo MAIN_HTML_HEAD;
  43.            $mainframe->profil_view();
  44.        }
  45.        break;
  46.    case "start":
  47.                // pokazuje pierwsza strone
  48.        echo MAIN_HTML_HEAD;
  49.        $form->menu();
  50.        echo "Witaj na stronie głównej!";
  51.        break;
  52.        
  53.    default:
  54.        header("location: /start");
  55.        echo MAIN_HTML_HEAD;
  56. }
  57. ?>


to może teraz include z mainframe()

  1. <?php
  2. class Mainframe
  3. {
  4.    function __construct()
  5.    {
  6.        $profil = Profil::getInstance();
  7.        $this->tab_profiles = new TabProfiles();
  8.    }
  9.  
  10.    function rejestracja($post)
  11.    {
  12.        $post=tablica_zabezpiecz($post);
  13.        $user = new Uzytkownik();
  14.        $user->setNazwa($post["username"]);
  15.        $user->setHaslo($post["password1"], $post["password2"]);
  16.        $user->setEmail($post["email"]);
  17.        if(!$user->zarejestruj()) { echo "Błąd podczas przesyłania danych do rejestracji!"; return false;}
  18.        return true;
  19.    }
  20.    function logowanie($post)
  21.    {
  22.        $post=tablica_zabezpiecz($post);
  23.        $user = new Uzytkownik();
  24.        if(!$user->loginUser($post["username"],$post["password"])) { echo "Błąd podczas logowania!"; return false; }
  25.        return true;
  26.    }
  27.    function wylogowanie()
  28.    {
  29.        Uzytkownik::logout();
  30.    }
  31.    function profil_view()
  32.    {
  33.        $profil = Profil::getInstance();
  34.        
  35.        $menu=new Form();
  36.        $menu->menu();
  37.        
  38.        $dane=tablica_odbezpiecz($profil->data);
  39.        
  40.        $form_profil = new Form();
  41.        $form_profil->setAction("/profil");
  42.        $form_profil->profil($dane);    //podstawianie pod profil i wywalanie formularza do edycji
  43.        
  44.        $form_foto = new Form();
  45.        $form_foto->setAction("/profil");
  46.        echo $form_foto->foto_user($dane);    //podstawianie pod profil i wywalanie formularza do edycji
  47.        
  48.    }
  49.    function profil_edit($post,$file)
  50.    {
  51.            $profil = Profil::getInstance();
  52.            $avatar = $profil->data["avatar"];
  53.            $zdjecie = $profil->data["zdjecie"];
  54.            switch($post["opcja"]) {
  55.                case "foto":
  56.                    $odp = $profil->load_files($file);
  57.                    
  58.                    if($odp[0] != false && $post["usun_avatar"] != "on")
  59.                    {
  60.                        $profil->data["avatar"] = $odp[0];
  61.                    }
  62.                    else if($post["usun_avatar"] == "on")
  63.                    {
  64.                        unlink($GLOBALS["imagedir_users"].$profil->data["avatar"]);
  65.                        $profil->data["avatar"] = false;
  66.                    }
  67.                    if($odp[1] != false && $post["usun_zdjecie"] != "on")
  68.                    {
  69.                        $profil->data["zdjecie"] =  $odp[1];
  70.                    }
  71.                    else if($post["usun_zdjecie"] == "on")
  72.                    {
  73.                        unlink($GLOBALS["imagedir_users"].$profil->data["zdjecie"]);
  74.                        $profil->data["zdjecie"] = false;
  75.                    }
  76.                    break;
  77.                case "zapisz":
  78.                    $profil->data = tablica_zabezpiecz($post);
  79.                    
  80.                    $profil->data["avatar"] = $avatar;
  81.                    $profil->data["zdjecie"] =  $zdjecie;
  82.                    break;
  83.            }
  84.            $profil->reload_sesja($profil);
  85.            $profil->zapisz();            
  86.    }    
  87. }
  88. ?>


tutaj czesc profil, konstruktor, sprawdza zalogowanie i dane w sesji przed powstaniem

  1. <?php
  2. class Profil
  3. {
  4.    public $profile_id="-1";
  5.    public $user_id="-1";
  6.    public $data=Array("");
  7.    
  8.    private static $instance;
  9.    private function __clone(){} //Uniemozliwia utworzenie kopii obiektu
  10.  
  11.    public static function getInstance ()
  12.    {
  13.        if (self::$instance === null) {
  14.            self::$instance = new self();
  15.        }
  16.        return self::$instance;
  17.    }
  18.    
  19.    private function __construct()
  20.    {
  21.        $sesja = Sesja::getInstance();
  22.        if(!$sesja->get("loggedin"))
  23.        {
  24.            $this->destroyer();
  25.            return false;
  26.        }
  27.        
  28.        $this->user_id = $sesja->get("id");
  29.        $this->profile_id = $this->getProfileIdFromUserID($sesja->get("id"));
  30.        
  31.        if(!$this->testProfil())
  32.        {
  33.            $this->data=Array();
  34.            $this->zapisz();
  35.        }
  36.        else
  37.        {
  38.            // na tej lekcji zrozumieliśmy, że lepiej trzymać data w sesji, niż za każdym razem odwoływać się do bazy (będzie mucho rapido)
  39.            if(!$sesja->get("profile_data"))
  40.            {
  41.                $sesja->set("profile_data",$this->dumpData());
  42.            }
  43.            $this->data = $sesja->get("profile_data");
  44.        }
  45.    }
  46.  
  47.    function dumpData()
  48.    {
  49.        $sesja=Sesja::getInstance();
  50.        $tabusers=TabUsers::getInstance();
  51.        
  52.        if(!$sesja->get("profile_data"))
  53.            {
  54.                $tab_profiles = TabProfiles::getInstance();
  55.                $this->data = TabProfiles::getAllData($this->profile_id); // zwraca false, jeśli nie ma profilu!
  56.                if(!$this->data)
  57.                {
  58.                    return false;
  59.                }
  60.                
  61.                $this->data["username"]=Sesja::get("name");
  62.                $this->data["email"]=$tabusers->getEmail(Sesja::get("name"));
  63.                $this->reload_sesja($this);
  64.            }
  65.        return $sesja->get("profile_data");
  66.    }
  67.    function reload_sesja(Profil $obj) // ta funkcja odczytuje aktualne dane z obiektu profil i zapisuje je do sesji
  68.    {
  69.        $sesja = Sesja::getInstance();
  70.        $sesja->set("profile_data", $obj->data);
  71.    }
  72. ?>


no i sama klasa sesja()

  1. <?php
  2. class Sesja
  3. {
  4.    public $id="-1";
  5.    public $profile_data;
  6.    
  7.    private static $instance;
  8.    private function __clone(){} //Uniemozliwia utworzenie kopii obiektu
  9.  
  10.    public static function getInstance ()
  11.    {
  12.        if (self::$instance === null) {
  13.            self::$instance = new self();
  14.        }
  15.        return self::$instance;
  16.    }
  17.  
  18.    private function __construct()
  19.    {
  20.        if(!$this->test())
  21.        {
  22.            session_start();
  23.            if($this->get("activity")) // zawiera czas ostatniej aktywnosci uzytkownika
  24.            {
  25.                    if(time()-$this->get("activity")>$GLOBALS['session_expired_time'])
  26.                    {
  27.                        $this->destroy();
  28.                    }
  29.                    $this->set("activity",time());
  30.            }
  31.            else if ($this->get("loggedin"))
  32.            {
  33.                $this->set("activity",time());
  34.            }
  35.        }
  36.        $this->id = $this->get("id");
  37.        $this->profile_data = $this->get("profile_data");
  38.    }    
  39.  
  40.    function test()
  41.    {
  42.        if(session_id()=="")
  43.        {
  44.            return false;
  45.        }
  46.        else
  47.        {
  48.            return true;
  49.        }    
  50.    }
  51.    function destroy()
  52.    {
  53.        if(Sesja::test())
  54.        {
  55.            fb::info("Zamykam sesję");
  56.            $this->set("loggedin",false);
  57.            $this->set("activity",false);
  58.            session_destroy();
  59.        }
  60.    }
  61.    function set($key,$val)
  62.    {
  63.        if(Sesja::test())
  64.        {
  65.            $_SESSION[$key]=$val;
  66.        }
  67.    }
  68.    function get($key)
  69.    {
  70.        if(Sesja::test() && array_key_exists($key, $_SESSION))
  71.        {
  72.            return $_SESSION[$key];
  73.        }
  74.        return false;
  75.    }    
  76. }
  77. ?>


... oraz uzytkownik ...

  1. <?php
  2. class Uzytkownik
  3. {
  4.    public $nazwa;
  5.    protected $haslo;
  6.    protected $ziarno;
  7.    protected $id;
  8.    public $email;
  9.    public $status;
  10.    public $profil_id;
  11.    
  12.    function __construct()
  13.    {
  14.        $sesja = Sesja::getInstance();
  15.        $tab_users = TabUsers::getInstance();
  16.        
  17.        if($sesja->test())
  18.        {
  19.            $this->nazwa=$sesja->get("name");
  20.            $this->id=$sesja->get("id");
  21.            $this->status=$sesja->get("status");
  22.            $this->email = $tab_users->getEmail($sesja->get("id"));
  23.        }
  24.    }
  25. ?>


  1. <?php
  2. function zarejestruj()
  3.    {
  4.        $tab_users = TabUsers::getInstance();
  5.        if($tab_users->existsUser($this->nazwa) == true) { echo "Istnieje już taki user! $this->nazwa<br>"; return false; }
  6.        if($tab_users->existsMail($this->email) == true) { echo "Istnieje już taki email! $this->email<br>"; return false; }
  7.      
  8.        $tab_users->addUser($this->nazwa, $this->haslo, $this->ziarno, $this->email);
  9.        return true;
  10.    }
  11.  
  12.    function setNazwa($nazwa)
  13.    {
  14.        $this->nazwa = stripslashes($nazwa);
  15.    }
  16.    function getNazwa()
  17.    {
  18.        return $this->nazwa;
  19.    }
  20.  
  21.    function setHaslo($haslo, $haslo2)
  22.    {
  23.        if($haslo != $haslo2) { echo "Różne hasła!<br>"; return false; }
  24.        if(empty($haslo) || empty($haslo2)) { echo "Jedno z haseł jest puste!<br>"; return false; }
  25.  
  26.        $this->ziarno=time();
  27.        $this->haslo = md5(stripslashes($haslo).$this->ziarno);
  28.        return true;
  29.    }
  30.  
  31.    function setEmail($email)
  32.    {
  33.        $this->email = stripslashes($email);
  34.    }
  35.    function loginUser($username,$password)
  36.    {
  37.        if(empty($username) || empty($password)) { echo "Nie podałeś loginu lub hasła<br>"; return false; }
  38.      
  39.        $tab_users = TabUsers::getInstance();
  40.        $sesja = Sesja::getInstance();
  41.      
  42.        fb::info($tab_users->existsUser($username),"existsUser($username)");
  43.        fb::info($tab_users->existsMail($username),"existsMail($username)");
  44.      
  45.        if(!$tab_users->existsUser($username))
  46.        {
  47.            if($tab_users->existsMail($username))
  48.            {
  49.                $this->id = $tab_users->getIdFromMail($username); // tak naprawde username to mail w tym wypadku
  50.                $this->nazwa = $tab_users->getNameFromId($this->id);
  51.            }
  52.            else
  53.            {
  54.                echo "Taki user nie istnieje!";
  55.                return false;
  56.            }
  57.        }
  58.        else
  59.        {
  60.            $this->id = $tab_users->getId($username);
  61.            $this->nazwa = $username;
  62.        }
  63.  
  64.        $this->haslo = md5($password.$tab_users->getSeed($this->nazwa));
  65.        $this->status = $tab_users->getStatus($this->nazwa);
  66.        $this->ziarno = $tab_users->getSeed($this->nazwa);
  67.      
  68.        if(!$tab_users->checkPass($this->nazwa,$this->haslo)) { echo "Złe hasło!"; return false; }
  69.      
  70.        $sesja->set("id",$this->id);
  71.        $sesja->set("name",$this->nazwa);
  72.        $sesja->set("loggedin", true);
  73.        $sesja->set("status",$this->status);
  74.      
  75.        return true;
  76.    }
  77.    function setProfil($id)
  78.    {
  79.        $this->profile_id = $id;
  80.    }
  81.    function logout()
  82.    {
  83.        unset($this->user);
  84.        unset($haslo);
  85.        unset($ziarno);
  86.        unset($id);
  87.        unset($email);
  88.        unset($status);
  89.        unset($profil_id);
  90.  
  91.        $sesja = Sesja::getInstance();
  92.        $sesja->destroy();
  93.    }
  94.  
  95. }
  96. ?>


To chyba wszystko. WIEEEEEEM, że sporo można zrobić lepiej i łatwiej, ale i tak jestem happy, że działa i poza wzorcem singletona chyba reszte zrobiłem sam. Ale za każde uwagi bede bardzo wdzieczny smile.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.