Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [php] klasa obsługująca sesję
Forum PHP.pl > Inne > Oceny
Black-Berry
Wiem że to sporo ale może ktoś już to robił albo jest w sesjach mastacha i będzie w stanie to ocenić.
  1. <?php
  2.    class Main_Session
  3.    {
  4.        private $data = array(); //data storage
  5.        private $sessionName = 'edicoSession';
  6.        private $sessionId = 0;
  7.        private $sessionActiveTime = 900;
  8.        private $folder;
  9.        private $activesSessionsList = array();
  10.        
  11.        public function __construct()
  12.        {
  13.            //current session folder...
  14.            $this->folder = MAIN_PATH . 'edc_session/';
  15.            //starting session...
  16.            $this->_start();
  17.            //testing run of the session...
  18.            if (array_key_exists('run',$this->data)) {
  19.               $this->data['run'] = $this->data['run'] + 1;
  20.            } else {
  21.                $this->data['run'] = 0;
  22.                $this->data['sessionCookie'] = $this->sessionId;
  23.                $this->data['browser'] = $_SERVER['HTTP_USER_AGENT'];
  24.                $this->startIp = $_SERVER['REMOTE_ADDR'];
  25.            }
  26.            //removing old session files...
  27.            $this->_updateActiveSessionsList();
  28.        }
  29.        
  30.        public function __destruct()
  31.        {
  32.            //saving session data to file...
  33.            $this->_save();
  34.        }
  35.        
  36.        public function __get($aKey)
  37.        {
  38.            //handeling magic get method...
  39.            if (isset($this->data[$aKey])) {
  40.                return $this->data[$aKey];
  41.            }
  42.        }
  43.        
  44.        private function __set($aKey, $aValue)
  45.        {
  46.            //handeling magic set method...
  47.            $this->data[$aKey] = $aValue;
  48.        }
  49.        
  50.        private function _start()
  51.        {
  52.            if ($_COOKIE[$this->sessionName] == '') {
  53.                //create new session and  sessionId...
  54.                $this->sessionId = encrypt(time()*rand(0,999999)).random_string(6);
  55.                setcookie($this->sessionName, $this->sessionId);
  56.            } else {
  57.                //load existing session file to use by this session...
  58.                $data = $this->_load($_COOKIE[$this->sessionName]);
  59.                if ($data['browser'] == $_SERVER['HTTP_USER_AGENT']) {
  60.                    //use existing cookie as sessionId...
  61.                    $this->sessionId = $_COOKIE[$this->sessionName];
  62.                    $this->data = $data;
  63.                } else {
  64.                    //cookie could have been stolen; start new session...
  65.                    $this->sessionId = encrypt(time(0,999999)*rand()).random_string(6);
  66.                    setcookie($this->sessionName, $this->sessionId);
  67.                }
  68.            }
  69.        }
  70.        
  71.        private function _load($aSessionId)
  72.        {
  73.            //creating session file name...
  74.            $fileName = $this->folder.$aSessionId.'.dat';
  75.            if (file_exists($fileName)) {
  76.                // geting data from file...
  77.                $file = fopen($fileName, 'r');
  78.                $data = fread($file, filesize($fileName)+1);
  79.                $data = unserialize($data);
  80.                fclose($file);
  81.            }
  82.            return $data;
  83.        }
  84.        
  85.        private function _save()
  86.        {
  87.            create_folder($this->folder);
  88.            //saving data to a file based on session id...
  89.            $file = fopen($this->folder.$this->sessionId.'.dat', 'w');
  90.            $data = $this->data;
  91.            //serializing data...
  92.            $data = serialize($data);
  93.            fwrite ($file, $data);
  94.            fclose($file);
  95.        }
  96.        
  97.        private function _updateActiveSessionsList()
  98.        {
  99.            $folder = opendir($this->folder);
  100.            while (($file = readdir($folder)) !== false) {
  101.                if ($file != '.' and $file != '..') {
  102.                    if(time() - filemtime($this->folder.$file) > $this->sessionActiveTime) {
  103.                        //deleting session file older then $this->sessionActiveTime
  104.                        unlink($this->folder.$file);
  105.                    } else {
  106.                        //saving info about all sessions to a variable for other use...
  107.                        $sessionFile = fopen($this->folder.$file, 'r');
  108.                        $data = fread($sessionFile, filesize($this->folder.$file)+1);
  109.                        $this->activesSessionsList[] = unserialize($data);
  110.                        fclose($sessionFile);
  111.                    }
  112.                }
  113.            }
  114.            closedir($folder);
  115.        }
  116.    }
  117. ?>
ahead
  1. <?php
  2. if ($data['browser'] == $_SERVER['HTTP_USER_AGENT'] ) {
  3.                    //use existing cookie as sessionId...
  4.                    $this->sessionId = $_COOKIE[$this->sessionName];
  5.                    $this->data = $data;
  6.                } else {
  7.                    //cookie could have been stolen; start new session...
  8.                    $this->sessionId = encrypt(time(0,999999)*rand()).random_string(6);
  9.                    setcookie($this->sessionName, $this->sessionId);
  10.                }
  11. ?>


Dodał bym jeszcze przechowywanie adresu ip usera w $data i sprawdziłbym czy zgadza się z aktualnym w tym miejscu. W przeciwnym wypadku, cookie można podstawić do tej samej przeglądarki. Ogólnie chyba wszystko jest ok.
Black-Berry
wie ktoś może jak ogrinalna sesja php radzi sobie z autentyfikacją użytkownika? Czy sprawdza przeglądarkę i IP ? Może ma jeszcze jakieś inne metody ?
SHiP
Jakie dużo winksmiley.jpg 120 linijek. Ja dawłem frameworka i ludzie odpowiadali biggrin.gif
  1. <?php
  2.               $file = fopen($fileName, 'r');
  3.               $data = fread($file, filesize($fileName)+1);
  4.               $data = unserialize($data);
  5.               fclose($file);
  6. ?>


1. To mi się nie podoba, wygląda jak przekombinowane file_get_contents" title="Zobacz w manualu PHP" target="_manual.
2. Za każdym razem wywołujesz funkcję czyszczącą stare sesje, która sprawdza czasy wszystkich plików po kolei. Jak wszyscy wiemy operacje na plikach są zabójczo wolne. Nie lepiej zrobić cache w postaci zserializowanej tablicy plików i czasów w jedym pliku? Myślę, że byłoby optymalniej przy większej ilości sesji.
EDIT:
Zapomniałem dopisać, że ogólnie bardzo fajna klasa winksmiley.jpg
3. dodaj __isset()
Black-Berry
bez cache'a się nie obejdzie bo już mi zaczeło mulić.

Myślisz ze na bazie mysql byłoby szybciej ? Miałem nadzieję że pliki będą szybsze i dlatego takie coś.
dr_bonzo
Pliki sa prostsze (hmm, u mnie niewiele szybsze), ale nie zliczysz ilosci aktywnych userow. Baze (lub cos innego) bedziesz musial uzyc jak bedziesz mial wiele serwerow z aplikacjami, zeby user mial na kazdym dostep do swojej sesji.
Black-Berry
słuszna uwaga z tymi wieloma serwerami. Mozna zliczyć pliki. Wtedy masz aktywnych userów. Nastawiam się na prędkość. Mam nadzieję że jak dodam cacha to będzie śmigac. Pracuję nad tym właśnie.
SHiP
@dr_bonzo: dało by się coś takiego napisać, wykły count();

Najlepiej byłoby stworzyć 2 wersje winksmiley.jpg. Ale moim skromnym zdaniem baza będze dużo lepszym rozwiązaniem. Po prostu daje dużo większą elastyczność. Jeśli portal urośnie do rozmiarow kilku tys sesji to będzie problem z operowaniem na takiej tablicy w php. Oczywiście to tylko gdybanie ;-).
Black-Berry
Po waszych radach i testach doszedłem do wniosku że pliki nie są takei fajne. Poza tym baza jest o niebo szybsza. Moje zmagania niech będą zatem przestrogą dla innych smile.gif Nowy kod. Jeszcze raz prosze o sugestie

  1. <?php
  2.    class Main_Session extends Main_Object
  3.    {
  4.        private $data = array(); //data storage
  5.        private $sessionId = 0;
  6.        private $sessionName = 'edicoSession';
  7.        
  8.        public function __construct()
  9.        {
  10.            parent__construct();
  11.            $this->dbTable = $this->settings->dbPrefix . 'edc_session_main';
  12.            $this->_start();
  13.            //testing run of the session...
  14.            if (array_key_exists('run',$this->data)) {
  15.               $this->data['run'] = $this->data['run'] + 1;
  16.            } else {
  17.                $this->data['run'] = 0;
  18.                $this->data['sessionCookie'] = $this->sessionId;
  19.                $this->data['browser'] = $_SERVER['HTTP_USER_AGENT'];
  20.                $this->startIp = $_SERVER['REMOTE_ADDR'];
  21.                $this->_cleanDatabase();
  22.            }
  23.        }
  24.        
  25.        public function install()
  26.        {
  27.            $query = "DROP TABLE IF EXISTS $this->dbTable";
  28.            $this->dbDriver->query($query);
  29.            $query = "CREATE TABLE $this->dbTable (
  30.                    `id` VARCHAR(64) NOT NULL, PRIMARY KEY(`id`),
  31.                    `last_update` DATETIME, INDEX (`last_update`),
  32.                    `data` TEXT
  33.                ) ENGINE=InnoDB CHARACTER SET `utf8`;";
  34.            $this->dbDriver->query($query);
  35.        }
  36.        
  37.        public function __destruct()
  38.        {
  39.            $this->_save($this->sessionId);
  40.        }
  41.        
  42.        
  43.        public function __get($aKey)
  44.        {
  45.            //handeling magic get method...
  46.            if (isset($this->data[$aKey])) {
  47.                return $this->data[$aKey];
  48.            }
  49.        }
  50.        
  51.        private function __set($aKey, $aValue)
  52.        {
  53.            //handeling magic set method...
  54.            $this->data[$aKey] = $aValue;
  55.        }
  56.        
  57.        private function _start()
  58.        {
  59.            if ($_COOKIE[$this->sessionName] == '') {
  60.                //create new session and  sessionId...
  61.                $this->sessionId = encrypt(time()*rand(0,999999)).random_string(6);
  62.                setcookie($this->sessionName, $this->sessionId);
  63.            } else {
  64.                //load existing session file to use by this session...
  65.                $data = $this->_load($_COOKIE[$this->sessionName]);
  66.                if ($data['browser'] == $_SERVER['HTTP_USER_AGENT']) {
  67.                    //use existing cookie as sessionId...
  68.                    $this->sessionId = $_COOKIE[$this->sessionName];
  69.                    $this->data = $data;
  70.                } else {
  71.                    //cookie could have been stolen; start new session...
  72.                    $this->sessionId = encrypt(time(0,999999)*rand()).random_string(6);
  73.                    setcookie($this->sessionName, $this->sessionId);
  74.                }
  75.            }
  76.            $this->log->addEntry(_SYSTEM_LOG_USER_SESSION_STARTED_IN_FOLDER_, $this->folder, NOTE);
  77.        }
  78.        
  79.        private function _cleanDatabase()
  80.        {
  81.            $this->dbDriver->query(
  82.                "DELETE FROM $this->dbTable WHERE `last_update` <= NOW() - INTERVAL 15 MINUTE"
  83.            );
  84.        }
  85.        
  86.        private function _load($aSessionId)
  87.        {
  88.            $this->dbDriver->query(
  89.                "SELECT * FROM $this->dbTable WHERE `id` = '$aSessionId'"
  90.            );
  91.            $row = $this->dbDriver->fetchRow();
  92.            return unserialize($row['data']);
  93.        }
  94.        
  95.        private function _save($aSessionId)
  96.        {
  97.            $this->dbDriver->query(
  98.                "INSERT INTO $this->dbTable SET
  99.                    `id` = '$aSessionId',
  100.                    `data` = '".serialize($this->data)."',
  101.                    `last_update` = NOW()
  102.                ON DUPLICATE KEY UPDATE
  103.                    `data` = '".serialize($this->data)."',
  104.                    `last_update` = NOW()"
  105.            );
  106.        }
  107.    }
  108. ?>
dr_bonzo
Co do zlicania aktywnych userow na plikach - zapomnialem ze skrypt USUWA nieaktywne pliki sesji. Wtedy sie da.
kbsucha
Cytat(Black-Berry @ 15.09.2008, 15:06:59 ) *
Po waszych radach i testach doszedłem do wniosku że pliki nie są takei fajne. Poza tym baza jest o niebo szybsza. Moje zmagania niech będą zatem przestrogą dla innych.


Wedlug mnie najlepiej by było, jakbyś zrobił możliwość wyboru (file, db), np. gdzies w pliku konfiguracyjnym. Wtedy miałbyś największe pole manewru w przyszlosci.

Pozdr
Black-Berry
Cytat(kbsucha @ 15.09.2008, 16:00:50 ) *
Wedlug mnie najlepiej by było, jakbyś zrobił możliwość wyboru (file, db), np. gdzies w pliku konfiguracyjnym. Wtedy miałbyś największe pole manewru w przyszlosci.

Pozdr

nie głupi pomysł. tak chyba zrobie.
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.