ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
SessionHandlerPHP.php
Go to the documentation of this file.
1<?php
2
12namespace SimpleSAML;
13
16
18{
19
25 protected $cookie_name;
26
37 private $previous_session = array();
38
39
44 protected function __construct()
45 {
46 // call the parent constructor in case it should become necessary in the future
47 parent::__construct();
48
50 $this->cookie_name = $config->getString('session.phpsession.cookiename', null);
51
52 if (session_status() === PHP_SESSION_ACTIVE) {
53 if (session_name() === $this->cookie_name || $this->cookie_name === null) {
54 Logger::warning(
55 'There is already a PHP session with the same name as SimpleSAMLphp\'s session, or the '.
56 "'session.phpsession.cookiename' configuration option is not set. Make sure to set ".
57 "SimpleSAMLphp's cookie name with a value not used by any other applications."
58 );
59 }
60
61 /*
62 * We shouldn't have a session at this point, so it might be an application session. Save the details to
63 * retrieve it later and commit.
64 */
65 $this->previous_session['cookie_params'] = session_get_cookie_params();
66 $this->previous_session['id'] = session_id();
67 $this->previous_session['name'] = session_name();
68 session_write_close();
69 }
70
71 if (!empty($this->cookie_name)) {
72 session_name($this->cookie_name);
73 } else {
74 $this->cookie_name = session_name();
75 }
76
77 $params = $this->getCookieParams();
78
79 if (!headers_sent()) {
80 session_set_cookie_params(
81 $params['lifetime'],
82 $params['path'],
83 $params['domain'],
84 $params['secure'],
85 $params['httponly']
86 );
87 }
88
89 $savepath = $config->getString('session.phpsession.savepath', null);
90 if (!empty($savepath)) {
91 session_save_path($savepath);
92 }
93 }
94
95
99 private function sessionStart()
100 {
101 $cacheLimiter = session_cache_limiter();
102 if (headers_sent()) {
103 /*
104 * session_start() tries to send HTTP headers depending on the configuration, according to the
105 * documentation:
106 *
107 * http://php.net/manual/en/function.session-start.php
108 *
109 * If headers have been already sent, it will then trigger an error since no more headers can be sent.
110 * Being unable to send headers does not mean we cannot recover the session by calling session_start(),
111 * so we still want to call it. In this case, though, we want to avoid session_start() to send any
112 * headers at all so that no error is generated, so we clear the cache limiter temporarily (no headers
113 * sent then) and restore it after successfully starting the session.
114 */
115 session_cache_limiter('');
116 }
117 session_cache_limiter($cacheLimiter);
118 @session_start();
119 }
120
121
132 public function restorePrevious()
133 {
134 if (empty($this->previous_session)) {
135 return; // nothing to do here
136 }
137
138 // close our own session
139 session_write_close();
140
141 session_name($this->previous_session['name']);
142 session_set_cookie_params(
143 $this->previous_session['cookie_params']['lifetime'],
144 $this->previous_session['cookie_params']['path'],
145 $this->previous_session['cookie_params']['domain'],
146 $this->previous_session['cookie_params']['secure'],
147 $this->previous_session['cookie_params']['httponly']
148 );
149 session_id($this->previous_session['id']);
150 $this->previous_session = array();
151 $this->sessionStart();
152
153 /*
154 * At this point, we have restored a previously-existing session, so we can't continue to use our session here.
155 * Therefore, we need to load our session again in case we need it. We remove this handler from the parent
156 * class so that the handler is initialized again if we ever need to do something with the session.
157 */
158 parent::$sessionHandler = null;
159 }
160
161
167 public function newSessionId()
168 {
169 // generate new (secure) session id
170 $sessionId = bin2hex(openssl_random_pseudo_bytes(16));
172
173 return $sessionId;
174 }
175
176
184 public function getCookieSessionId()
185 {
186 if (!self::hasSessionCookie()) {
187 return null; // there's no session cookie, can't return ID
188 }
189
190 // do not rely on session_id() as it can return the ID of a previous session. Get it from the cookie instead.
191 session_id($_COOKIE[$this->cookie_name]);
192
193 $session_cookie_params = session_get_cookie_params();
194
195 if ($session_cookie_params['secure'] && !HTTP::isHTTPS()) {
196 throw new \SimpleSAML_Error_Exception('Session start with secure cookie not allowed on http.');
197 }
198
199 $this->sessionStart();
200 return session_id();
201 }
202
203
209 public function getSessionCookieName()
210 {
211 return $this->cookie_name;
212 }
213
214
221 {
222 $_SESSION['SimpleSAMLphp_SESSION'] = serialize($session);
223 }
224
225
236 public function loadSession($sessionId = null)
237 {
238 assert(is_string($sessionId) || $sessionId === null);
239
240 if ($sessionId !== null) {
241 if (session_id() === '') {
242 // session not initiated with getCookieSessionId(), start session without setting cookie
243 $ret = ini_set('session.use_cookies', '0');
244 if ($ret === false) {
245 throw new \SimpleSAML_Error_Exception('Disabling PHP option session.use_cookies failed.');
246 }
247
248 session_id($sessionId);
249 $this->sessionStart();
250 } elseif ($sessionId !== session_id()) {
251 throw new \SimpleSAML_Error_Exception('Cannot load PHP session with a specific ID.');
252 }
253 } elseif (session_id() === '') {
254 self::getCookieSessionId();
255 }
256
257 if (!isset($_SESSION['SimpleSAMLphp_SESSION'])) {
258 return null;
259 }
260
261 $session = $_SESSION['SimpleSAMLphp_SESSION'];
262 assert(is_string($session));
263
264 $session = unserialize($session);
265
266 return ($session !== false) ? $session : null;
267 }
268
269
277 public function hasSessionCookie()
278 {
279 return array_key_exists($this->cookie_name, $_COOKIE);
280 }
281
282
294 public function getCookieParams()
295 {
297
298 $ret = parent::getCookieParams();
299
300 if ($config->hasValue('session.phpsession.limitedpath') && $config->hasValue('session.cookie.path')) {
301 throw new \SimpleSAML_Error_Exception(
302 'You cannot set both the session.phpsession.limitedpath and session.cookie.path options.'
303 );
304 } elseif ($config->hasValue('session.phpsession.limitedpath')) {
305 $ret['path'] = $config->getBoolean(
306 'session.phpsession.limitedpath',
307 false
308 ) ? $config->getBasePath() : '/';
309 }
310
311 $ret['httponly'] = $config->getBoolean('session.phpsession.httponly', true);
312
313 return $ret;
314 }
315
316
326 public function setCookie($sessionName, $sessionID, array $cookieParams = null)
327 {
328 if ($cookieParams === null) {
329 $cookieParams = session_get_cookie_params();
330 }
331
332 if ($cookieParams['secure'] && !HTTP::isHTTPS()) {
333 throw new CannotSetCookie(
334 'Setting secure cookie on plain HTTP is not allowed.',
335 CannotSetCookie::SECURE_COOKIE
336 );
337 }
338
339 if (headers_sent()) {
340 throw new CannotSetCookie(
341 'Headers already sent.',
342 CannotSetCookie::HEADERS_SENT
343 );
344 }
345
346 if (session_id() !== '') {
347 // session already started, close it
348 session_write_close();
349 }
350
351 session_set_cookie_params(
352 $cookieParams['lifetime'],
353 $cookieParams['path'],
354 $cookieParams['domain'],
355 $cookieParams['secure'],
356 $cookieParams['httponly']
357 );
358
359 session_id($sessionID);
360 $this->sessionStart();
361 }
362}
$_COOKIE['client_id']
Definition: server.php:9
$_SESSION["AccountId"]
An exception for terminatinating execution or to throw for unit testing.
getSessionCookieName()
Retrieve the session cookie name.
setCookie($sessionName, $sessionID, array $cookieParams=null)
Set a session cookie.
getCookieSessionId()
Retrieve the session ID saved in the session cookie, if there's one.
newSessionId()
Create a new session id.
sessionStart()
This method starts a session, making sure no warnings are generated due to headers being already sent...
getCookieParams()
Get the cookie parameters that should be used for session cookies.
loadSession($sessionId=null)
Load the session from the PHP session array.
__construct()
Initialize the PHP session handling.
hasSessionCookie()
Check whether the session cookie is set.
restorePrevious()
Restore a previously-existing session.
saveSession(\SimpleSAML_Session $session)
Save the current session to the PHP session array.
static getInstance($instancename='simplesaml')
Get a configuration file by its instance name.
static createSession($sessionId)
Create a new session and cache it.
Definition: Session.php:416
$config
Definition: bootstrap.php:15
Attribute-related utility methods.
$ret
Definition: parser.php:6
$session
$sessionID