Witam. Napisałem ostatnio własny mechanizm sesji, który korzysta z bazy i ciasteczek.
Oto kod:
  1. <?php
  2. class sessions extends dbTable {
  3. public $_name = 'sessions'; //nazwa tabeli w bazie z sesjami
  4. private $ua = null; //user_agent
  5. private $ip = null; //remote_addr;
  6. private $SID = null; //id sesji
  7. private $vars = array(); //zmienne sesji
  8. protected $timeOut = 3600; //czas wygaśnięcia sesji w sekundach
  9. private function __clone(){}
  10. private static $instance = false; //zmienna instancji klasy
  11.  
  12. public function __construct(){
  13. parent::__construct();
  14. $this->ua = strtolower($_SERVER['HTTP_USER_AGENT']);
  15. $this->ip = $_SERVER['REMOTE_ADDR'];
  16. $this->checkSession();
  17. }
  18.  
  19. /*
  20. zwraca instancję klasy. w przypadku kiedy nie istnieje tworzy ją
  21. */
  22. public static function getInstance() {
  23. if (!self::$instance) {
  24. self::$instance = new sessions();
  25. }
  26. return self::$instance;
  27. }
  28.  
  29. /*
  30. zwraca nazwę przeglądarki
  31. */
  32. public function getBrowser(){
  33. $browsers = array(
  34. 'mozilla'=>'mozilla',
  35. 'opera'=>'opera',
  36. 'msie'=>'msie',
  37. 'netscape'=>'netscape',
  38. 'konqueror'=>'konqueror',
  39. 'galeon'=>'galeon',
  40. 'firefox'=>'firefox',
  41. 'netsprint'=>'netsprint',
  42. 'firebird'=>'firebird',
  43. 'links'=>'links',
  44. 'lynks'=>'lynks',
  45. 'meleon'=>'kmeleon',
  46. 'dillo'=>'dillo',
  47. 'omniweb'=>'omniweb',
  48. 'avant'=>'avant',
  49. 'myie2'=>'myie2',
  50. 'seamonkey'=>'seamonkey',
  51. 'maxthon'=>'maxthon',
  52. 'chrome'=>'chrome',
  53. 'safari'=>'safari');
  54. foreach($browsers as $browser=>$name){
  55. if(strpos($this->ua, $browser) !== false){
  56. return $name;
  57. }
  58. return 'unknown';
  59. }
  60. }
  61.  
  62. /*
  63. zwraca system operacyjny klienta
  64. */
  65. public function getOS(){
  66. $OSs = array(
  67. 'windows'=>array(
  68. 'nt 4.0'=>'windows98',
  69. 'nt 5.0'=>'windows2000',
  70. 'nt 5.1'=>'windowsXP',
  71. 'nt 5.2'=>'windowsXP',
  72. 'nt 6.0'=>'windowsVista',
  73. 'nt 6.1'=>'windows7',
  74. 'nt 6.2'=>'windows8',
  75. 'default'=>'windows'
  76. ),
  77. 'linux'=>array(
  78. 'suse'=>'suse',
  79. 'knoppix'=>'knoppix',
  80. 'turbolinux'=>'turbolinux',
  81. 'slackware'=>'slackware',
  82. 'gentoo'=>'gentoo',
  83. 'lycoris'=>'lycoris',
  84. 'debian'=>'debian',
  85. 'redhat'=>'redhat',
  86. 'archlinux'=>'arch',
  87. 'kubuntu'=>'kubuntu',
  88. 'ubuntu'=>'ubuntu',
  89. 'mandriva'=>'mandriva',
  90. 'slax'=>'slax',
  91. 'mint'=>'mint',
  92. 'centos'=>'centos',
  93. 'fedora'=>'fedora',
  94. 'openbsd'=>'openbsd',
  95. 'netbsd'=>'netbsd',
  96. 'pc-bsd'=>'pcbsd',
  97. 'bsd'=>'freebsd',
  98. 'default'=>'linux'
  99. ));
  100. foreach($OSs as $OS=>$system){
  101. foreach($system as $os2=>$name){
  102. if(strpos($this->ua, $os2) !== false){
  103. return $name;
  104. }
  105. }
  106. if(strpos($this->ua, $OS) !== false){
  107. return $system['default'];
  108. }
  109. else{
  110. continue;
  111. }
  112. }
  113. }
  114. /*
  115. zwraca ip klienta
  116. */
  117. public function getIP(){
  118. return $this->ip;
  119. }
  120.  
  121. /*
  122. inicjuje zmienną lub zmienia jej wartość
  123. */
  124. public function _set($name, $value){
  125. return ($this->vars[$name]=$value) ? true : false;
  126. }
  127.  
  128. /*
  129. zwraca wartość zmiennej
  130. */
  131. public function _get($name){
  132. return (isSet($this->vars[$name])==true) ? $this->vars[$name] : false;
  133. }
  134.  
  135. /*
  136. usuwa zmienna
  137. */
  138. public function _unset($name){
  139. unset($this->vars[$name]);
  140. }
  141.  
  142. /*
  143. zwraca zmienne sesji
  144. */
  145. public function _getAll(){
  146. return $this->vars;
  147. }
  148.  
  149. /*
  150. generuje id sesji
  151. */
  152. public function generateSID(){
  153. return ($this->SID = md5(md5(uniqid(mt_rand(),1)).microtime().$_SERVER['REMOTE_ADDR'].$_SERVER['REMOTE_PORT'].serialize($_SERVER)))?true:false;
  154. }
  155.  
  156. /*
  157. rozpoczyna sesje, tworzy ciasteczko i nowy wpis w bazie
  158. */
  159. public function sessionStart(){
  160. $this->generateSID();
  161. $sid = $this->SID;
  162. $timeOut = time()+$this->timeOut;
  163. setCookie('RPFSID', $sid, $timeOut, '/szp/', '');
  164. $_COOKIE['RPFSID'] = $sid;
  165. $data = array(
  166. 'ip'=>$this->ip,
  167. 'przegladarka'=>$this->getBrowser(),
  168. 'system'=>$this->getOS(),
  169. 'zmienne'=>'',
  170. 'czasWygasniecia'=>$timeOut,
  171. 'idSesji'=>$sid
  172. );
  173. return $this->insert($data, $this->_name);
  174. }
  175.  
  176. /*
  177. niszczy sesje
  178. */
  179. public function sessionDestroy(){
  180. setCookie('RPFSID', '', time() - $this->timeOut);
  181. $this->where('ip = ?', $this->ip)->where('idSesji = ?', $this->SID)->cache(false)->delete($this->_name);
  182. }
  183. /*
  184. sprawdza czy sesja jest poprawna, jeśli jest to sprawdza poprawność SID i przypisuje zmienne, jeśli nie to tworzy nową
  185. */
  186. public function checkSession(){
  187. if($this->sessionExist() == false){
  188. if($this->sessionStart() === false){
  189. return false;
  190. }
  191. }
  192. $result = $this->select()->from($this->_name)->where('ip = ?', $this->ip)->cache(false)->sql()->fetchObject();
  193. $result = $result[0];
  194. if($result->przegladarka == $this->getBrowser() && $result->system == $this->getOS()){
  195. $this->vars = unserialize($result->zmienne);
  196. $this->SID = $result->idSesji;
  197. $this->refreshSession();
  198. return true;
  199. }
  200. return false;
  201. }
  202. /*
  203. sprawdza czy sesja istnieje
  204. */
  205. public function sessionExist(){
  206. $result = $this->select()->from()->where('ip = ?', $this->ip)->cache(false)->sql()->fetchObject();
  207. if(empty($result) == false && isSet($_COOKIE['RPFSID']) == true && $result[0]->idSesji == $_COOKIE['RPFSID']){
  208. return true;
  209. }
  210. if(empty($result) == false || $result->czasWygasniecia < time()){
  211. $this->where('ip = ?', $this->ip)->delete($this->_name);
  212. }
  213. return false;
  214. }
  215.  
  216. /*
  217. zapisuje zmienne do bazy
  218. */
  219. public function saveVars(){
  220. return $this->where('ip = ?', $this->ip)->where('idSesji = ?', $this->SID)->cache(false)->update(array('zmienne'=>serialize($this->vars)), $this->_name);
  221. }
  222.  
  223. /*
  224. odświeża czas wygaśnięcia sesji
  225. */
  226. public function refreshSession(){
  227. $timeOut = time() + $this->timeOut;
  228. setCookie('RPFSID', $this->SID, $timeOut);
  229. $this->where('ip = ?', $this->ip)->where('idSesji = ?', $this->SID)->cache(false)->update(array('czasWygasniecia'=>$timeOut), $this->_name, true);
  230. }
  231.  
  232. public function _destruct(){
  233. parent::__destruct();
  234. $this->saveVars();
  235. }
  236. }
  237. ?>

Problem polega na tym, że raz mogę się zalogować, zmienne są w bazie, ciasteczko istnieje, odświeżając stronę sesja nadal jest, ale gdy przechodzę na inna podstronę to sesja ginie, zmienia się id sesji, znikają zmienne etc. Dziwne jest to, że raz działa, a raz nie, raz się loguje za 1 razem, nieraz za n-tym. Zauważyłem również, że usunięcie rekordu z tabeli sesji i ręczne usunięcie ciasteczek poprawia sytuację w ten sposób, że normalnie się loguje i poruszam po stronie, sesja nie ginie. Ale gdy tylko się wyloguje i chcę od nowa zalogować problem powraca. Może wiecie co jest źle zrobione, bo ja już się z tym męczę od paru dni i nic...