]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - application/security/SessionManager.php
Refactor session and cookie timeout control
[github/shaarli/Shaarli.git] / application / security / SessionManager.php
CommitLineData
ebd650c0 1<?php
fab87c26 2namespace Shaarli\Security;
ebd650c0 3
c7721487
V
4use Shaarli\Config\ConfigManager;
5
ebd650c0
V
6/**
7 * Manages the server-side session
8 */
9class SessionManager
10{
c7721487 11 /** @var int Session expiration timeout, in seconds */
51f0128c
V
12 public static $SHORT_TIMEOUT = 3600; // 1 hour
13
14 /** @var int Session expiration timeout, in seconds */
15 public static $LONG_TIMEOUT = 31536000; // 1 year
db45a36a 16
c7721487 17 /** @var string Name of the cookie set after logging in **/
49f18323
V
18 public static $LOGGED_IN_COOKIE = 'shaarli_staySignedIn';
19
c7721487 20 /** @var array Local reference to the global $_SESSION array */
ebd650c0
V
21 protected $session = [];
22
c7721487 23 /** @var ConfigManager Configuration Manager instance **/
49f18323
V
24 protected $conf = null;
25
51f0128c
V
26 /** @var bool Whether the user should stay signed in (LONG_TIMEOUT) */
27 protected $staySignedIn = false;
28
ebd650c0
V
29 /**
30 * Constructor
31 *
32 * @param array $session The $_SESSION array (reference)
dd883aaf 33 * @param ConfigManager $conf ConfigManager instance
ebd650c0 34 */
dd883aaf 35 public function __construct(& $session, $conf)
ebd650c0
V
36 {
37 $this->session = &$session;
dd883aaf 38 $this->conf = $conf;
ebd650c0
V
39 }
40
51f0128c
V
41 /**
42 * Define whether the user should stay signed in across browser sessions
43 *
44 * @param bool $staySignedIn Keep the user signed in
45 */
46 public function setStaySignedIn($staySignedIn)
47 {
48 $this->staySignedIn = $staySignedIn;
49 }
50
ebd650c0
V
51 /**
52 * Generates a session token
53 *
54 * @return string token
55 */
56 public function generateToken()
57 {
58 $token = sha1(uniqid('', true) .'_'. mt_rand() . $this->conf->get('credentials.salt'));
59 $this->session['tokens'][$token] = 1;
60 return $token;
61 }
62
63 /**
64 * Checks the validity of a session token, and destroys it afterwards
65 *
66 * @param string $token The token to check
67 *
68 * @return bool true if the token is valid, else false
69 */
70 public function checkToken($token)
71 {
72 if (! isset($this->session['tokens'][$token])) {
73 // the token is wrong, or has already been used
74 return false;
75 }
76
77 // destroy the token to prevent future use
78 unset($this->session['tokens'][$token]);
79 return true;
80 }
fd7d8461
V
81
82 /**
83 * Validate session ID to prevent Full Path Disclosure.
84 *
85 * See #298.
86 * The session ID's format depends on the hash algorithm set in PHP settings
87 *
88 * @param string $sessionId Session ID
89 *
90 * @return true if valid, false otherwise.
91 *
92 * @see http://php.net/manual/en/function.hash-algos.php
93 * @see http://php.net/manual/en/session.configuration.php
94 */
95 public static function checkId($sessionId)
96 {
97 if (empty($sessionId)) {
98 return false;
99 }
100
101 if (!$sessionId) {
102 return false;
103 }
104
105 if (!preg_match('/^[a-zA-Z0-9,-]{2,128}$/', $sessionId)) {
106 return false;
107 }
108
109 return true;
110 }
49f18323
V
111
112 /**
113 * Store user login information after a successful login
114 *
c7721487 115 * @param string $clientIpId Client IP address identifier
49f18323 116 */
c7721487 117 public function storeLoginInfo($clientIpId)
49f18323
V
118 {
119 // Generate unique random number (different than phpsessionid)
120 $this->session['uid'] = sha1(uniqid('', true) . '_' . mt_rand());
c7721487 121 $this->session['ip'] = $clientIpId;
49f18323 122 $this->session['username'] = $this->conf->get('credentials.login');
51f0128c 123 $this->extendTimeValidityBy(self::$SHORT_TIMEOUT);
49f18323
V
124 }
125
c7721487
V
126 /**
127 * Extend session validity
128 */
129 public function extendSession()
130 {
51f0128c
V
131 if ($this->staySignedIn) {
132 return $this->extendTimeValidityBy(self::$LONG_TIMEOUT);
c7721487 133 }
51f0128c
V
134 return $this->extendTimeValidityBy(self::$SHORT_TIMEOUT);
135 }
136
137 /**
138 * Extend expiration time
139 *
140 * @param int $duration Expiration time extension (seconds)
141 *
142 * @return int New session expiration time
143 */
144 protected function extendTimeValidityBy($duration)
145 {
146 $expirationTime = time() + $duration;
147 $this->session['expires_on'] = $expirationTime;
148 return $expirationTime;
c7721487
V
149 }
150
49f18323
V
151 /**
152 * Logout a user by unsetting all login information
153 *
154 * See:
155 * - https://secure.php.net/manual/en/function.setcookie.php
49f18323 156 */
51f0128c 157 public function logout()
49f18323
V
158 {
159 if (isset($this->session)) {
160 unset($this->session['uid']);
161 unset($this->session['ip']);
51f0128c 162 unset($this->session['expires_on']);
49f18323
V
163 unset($this->session['username']);
164 unset($this->session['visibility']);
165 unset($this->session['untaggedonly']);
166 }
49f18323 167 }
c7721487
V
168
169 /**
170 * Check whether the session has expired
171 *
172 * @param string $clientIpId Client IP address identifier
173 *
174 * @return bool true if the session has expired, false otherwise
175 */
176 public function hasSessionExpired()
177 {
178 if (empty($this->session['uid'])) {
179 return true;
180 }
181 if (time() >= $this->session['expires_on']) {
182 return true;
183 }
184 return false;
185 }
186
187 /**
188 * Check whether the client IP address has changed
189 *
190 * @param string $clientIpId Client IP address identifier
191 *
192 * @return bool true if the IP has changed, false if it has not, or
193 * if session protection has been disabled
194 */
195 public function hasClientIpChanged($clientIpId)
196 {
197 if ($this->conf->get('security.session_protection_disabled') === true) {
198 return false;
199 }
200 if ($this->session['ip'] == $clientIpId) {
201 return false;
202 }
203 return true;
204 }
ebd650c0 205}