Session Handler Class, wordt steeds uitgelogd.
Ik heb sinds een half jaar een eigen PHP Session Handler Class geschreven.
Deze logt mij op random momenten uit, Het ene moment kan ik 2 uur zonder problemen werken op de site, het ander moment logt hij mij uit na de 2e klik binnen 1 minuut.
Als ik in de database kijk naar de laatste "view" tijd, dan staat deze wel goed ingesteld, de sessie is dus wel uitgelezen.
Hieronder mijn class:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<?php
class CSessionHandler implements SessionHandlerInterface
{
public static $SessionID = NULL;
public static $iSessionLifetime = 3600; // 30 minuten
public function __construct ( )
{
if ( is_numeric ( SYSTEM::GetSetting ( 'sysSessionLifetime' ) ) )
{
self::$iSessionLifetime = SYSTEM::GetSetting ( 'sysSessionLifetime' );
}
if ( ! session_set_save_handler ( $this ) )
{
new CLog ( 9009, 'Unable to implement our CSessionHandler. Please track the issue and fix this.' );
return;
}
ini_set ( 'session.gc_maxlifetime', self::$iSessionLifetime ); // expires in 30 minutes
ini_set ( 'session.cookie_lifetime', self::$iSessionLifetime ); // 30 minutes
ini_set ( 'session.save_path', dirname ( dirname ( __DIR__ ) ) . '/sessions' );
session_set_cookie_params ( self::$iSessionLifetime );
session_start ( );
}
public function open ( $sSavePath, $sSessionName )
{
// No need to open DB connection. (called at "session_start ( );")
return true;
}
public function close ( )
{
// No need to close DB connection.
$this->gc(); // Linux doesn't call the clean function, but uses a cronjob to delete session files.
return true;
}
public function read ( $sSessionID )
{
$oQuery = DB::Query ( "SELECT SessionValue FROM Sessions WHERE SessionID = ? AND TIMESTAMPDIFF(SECOND, SessionTime, NOW()) <= " . self::$iSessionLifetime, $sSessionID );
if ( DB::Num ( $oQuery ) > 0 )
{
DB::Query ( "UPDATE Sessions SET SessionTime = NOW() WHERE SessionID = ?", $sSessionID );
$aFetch = DB::Fetch ( $oQuery );
return $aFetch['SessionValue'];
}
return ''; // Session not set, return empty string. IMPORTANT!
}
public function write ( $sSessionID, $sSessionValue )
{
$oQuery = DB::Query ( "SELECT SessionID FROM Sessions WHERE SessionID = ?", $sSessionID );
if ( DB::Num ( $oQuery ) > 0 )
{
DB::Query ( "UPDATE Sessions SET SessionTime = NOW(), SessionValue = ? WHERE SessionID = ?", $sSessionValue, $sSessionID );
return true;
}
DB::Query ( "INSERT INTO Sessions (SessionID, SessionValue) VALUES (?,?)", $sSessionID, $sSessionValue );
return true;
}
public function destroy ( $sSessionID )
{
DB::Query ( "DELETE FROM Sessions WHERE SessionID = ?", $sSessionID );
return true;
}
public function gc ( $iSessionLifetime = null )
{
DB::Query ( "DELETE FROM Sessions WHERE TIMESTAMPDIFF(SECOND, SessionTime, NOW()) > " . self::$iSessionLifetime );
return true;
}
public static function GetActiveUserSessions ( )
{
$oQuery = DB::Query ( "SELECT * FROM Sessions WHERE SessionValue LIKE '%userID%' AND TIMESTAMPDIFF(SECOND, SessionTime, NOW()) < " . self::$iSessionLifetime . " GROUP BY SessionID" );
return DB::Num ( $oQuery );
}
}
?>
class CSessionHandler implements SessionHandlerInterface
{
public static $SessionID = NULL;
public static $iSessionLifetime = 3600; // 30 minuten
public function __construct ( )
{
if ( is_numeric ( SYSTEM::GetSetting ( 'sysSessionLifetime' ) ) )
{
self::$iSessionLifetime = SYSTEM::GetSetting ( 'sysSessionLifetime' );
}
if ( ! session_set_save_handler ( $this ) )
{
new CLog ( 9009, 'Unable to implement our CSessionHandler. Please track the issue and fix this.' );
return;
}
ini_set ( 'session.gc_maxlifetime', self::$iSessionLifetime ); // expires in 30 minutes
ini_set ( 'session.cookie_lifetime', self::$iSessionLifetime ); // 30 minutes
ini_set ( 'session.save_path', dirname ( dirname ( __DIR__ ) ) . '/sessions' );
session_set_cookie_params ( self::$iSessionLifetime );
session_start ( );
}
public function open ( $sSavePath, $sSessionName )
{
// No need to open DB connection. (called at "session_start ( );")
return true;
}
public function close ( )
{
// No need to close DB connection.
$this->gc(); // Linux doesn't call the clean function, but uses a cronjob to delete session files.
return true;
}
public function read ( $sSessionID )
{
$oQuery = DB::Query ( "SELECT SessionValue FROM Sessions WHERE SessionID = ? AND TIMESTAMPDIFF(SECOND, SessionTime, NOW()) <= " . self::$iSessionLifetime, $sSessionID );
if ( DB::Num ( $oQuery ) > 0 )
{
DB::Query ( "UPDATE Sessions SET SessionTime = NOW() WHERE SessionID = ?", $sSessionID );
$aFetch = DB::Fetch ( $oQuery );
return $aFetch['SessionValue'];
}
return ''; // Session not set, return empty string. IMPORTANT!
}
public function write ( $sSessionID, $sSessionValue )
{
$oQuery = DB::Query ( "SELECT SessionID FROM Sessions WHERE SessionID = ?", $sSessionID );
if ( DB::Num ( $oQuery ) > 0 )
{
DB::Query ( "UPDATE Sessions SET SessionTime = NOW(), SessionValue = ? WHERE SessionID = ?", $sSessionValue, $sSessionID );
return true;
}
DB::Query ( "INSERT INTO Sessions (SessionID, SessionValue) VALUES (?,?)", $sSessionID, $sSessionValue );
return true;
}
public function destroy ( $sSessionID )
{
DB::Query ( "DELETE FROM Sessions WHERE SessionID = ?", $sSessionID );
return true;
}
public function gc ( $iSessionLifetime = null )
{
DB::Query ( "DELETE FROM Sessions WHERE TIMESTAMPDIFF(SECOND, SessionTime, NOW()) > " . self::$iSessionLifetime );
return true;
}
public static function GetActiveUserSessions ( )
{
$oQuery = DB::Query ( "SELECT * FROM Sessions WHERE SessionValue LIKE '%userID%' AND TIMESTAMPDIFF(SECOND, SessionTime, NOW()) < " . self::$iSessionLifetime . " GROUP BY SessionID" );
return DB::Num ( $oQuery );
}
}
?>
Zoals jullie zien heb ik al diverse pogingen gedaan via ini_set, maar helaas.
Bij het deactiveren van deze class werkt alles weer naar behoren.
Zien jullie waar het probleem zit?
Gewijzigd op 26/01/2016 09:56:45 door Henk van Loo
http://stackoverflow.com/a/30968208
http://php.net/manual/en/function.session-set-cookie-params.php#100657
http://php.net/manual/en/function.session-set-cookie-params.php#100657
Daarnaast het volgende: de webserver waarop deze code actief is, is dit een Windows platform of iets anders? Volgens mij was er iets op Windows platformen waarbij sessies eerder als "verlopen" aangezien worden door de garbage collector omdat er op deze platformen er enkel zoiets is (of was, wellicht is dit inmiddels veranderd) als een modificatietijd, en niet (zoals op Unix/linux platformen) een accesstijd. Oftewel, op een Windows platform wordt het opvragen van een sessie-bestand niet geregistreerd waardoor deze, of deze nu actief is of niet, altijd op een vast moment vanaf zijn creatie verloopt. Een manier om dit (op Windows platformen) tegen te gaan is bijvoorbeeld het wegschrijven van een bitje zodat de modificatietijd elke "access" een schop krijgt.
EDIT, bijvoorbeeld zoiets, in zijn simpelste vorm:
Code (php)
1
2
3
4
2
3
4
<?php
// aanname: bij creatie van de sessie krijgt dit veld een initiële waarde (1 of 0)
$_SESSION['pingpong'] = 1 - $_SESSION['pingpong']; // flip de waarde
?>
// aanname: bij creatie van de sessie krijgt dit veld een initiële waarde (1 of 0)
$_SESSION['pingpong'] = 1 - $_SESSION['pingpong']; // flip de waarde
?>
Maar omdat je timeouts zo grillig verlopen is er mogelijk meer of iets anders aan de hand.
@Elmar vH: mogelijk zit je in de goede richting, maar het helpt om die informatie hier nogmaals te herhalen zodat iemand het zoekwerk niet nogmaals hoeft te doen en dat de informatie ook behouden blijft mocht de externe bron(nen) komen te vervallen.
Gewijzigd op 26/01/2016 14:43:41 door Thomas van den Heuvel
Ik zal jullie opmerkingen verwerken in het systeem, ik zal de uitkomst laten weten.
Het script draaide eerst op Windows, alleen deze voerde mijn Cronjobs (via de task scheduler) ineens niet meer goed uit waardoor ik weer terug gegaan ben naar mijn oude vertrouwde Linux server.
Bedankt.
Toevoeging op 30/01/2016 12:25:53:
De sessie cookie wordt nu aangepast, dit heb ik gecontroleerd. Dit was inderdaad eerder niet het geval, ik zal het eens aankijken vandaag.
Daarnaast werk ik inderdaad met SEO vriendelijke URLs, de cookies werden inderdaad geset op /portal. Ik heb dit aangepast zodat ze nu '/' als path hebben. Wat dom dat ik daar niet op gelet heb.
Uiteraard had ik zelf ook al gezocht, maar als je niet weet waar de fout zit is het zoeken een uitdaging.
Dank u wel heren. Alles lijkt te functioneren!