ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 (function_exists('session_status') && defined('PHP_SESSION_ACTIVE')) { // PHP >= 5.4
53 $previous_session = session_status() === PHP_SESSION_ACTIVE;
54 } else {
55 $previous_session = (session_id() !== '') && (session_name() !== $this->cookie_name);
56 }
57
58 if ($previous_session) {
59 if (session_name() === $this->cookie_name || $this->cookie_name === null) {
60 Logger::warning(
61 'There is already a PHP session with the same name as SimpleSAMLphp\'s session, or the '.
62 "'session.phpsession.cookiename' configuration option is not set. Make sure to set ".
63 "SimpleSAMLphp's cookie name with a value not used by any other applications."
64 );
65 }
66
67 /*
68 * We shouldn't have a session at this point, so it might be an application session. Save the details to
69 * retrieve it later and commit.
70 */
71 $this->previous_session['cookie_params'] = session_get_cookie_params();
72 $this->previous_session['id'] = session_id();
73 $this->previous_session['name'] = session_name();
74 session_write_close();
75 }
76
77 if (!empty($this->cookie_name)) {
78 session_name($this->cookie_name);
79 } else {
80 $this->cookie_name = session_name();
81 }
82
83 $params = $this->getCookieParams();
84
85 session_set_cookie_params(
86 $params['lifetime'],
87 $params['path'],
88 $params['domain'],
89 $params['secure'],
90 $params['httponly']
91 );
92
93 $savepath = $config->getString('session.phpsession.savepath', null);
94 if (!empty($savepath)) {
95 session_save_path($savepath);
96 }
97 }
98
99
103 private function sessionStart()
104 {
105 $cacheLimiter = session_cache_limiter();
106 if (headers_sent()) {
107 /*
108 * session_start() tries to send HTTP headers depending on the configuration, according to the
109 * documentation:
110 *
111 * http://php.net/manual/en/function.session-start.php
112 *
113 * If headers have been already sent, it will then trigger an error since no more headers can be sent.
114 * Being unable to send headers does not mean we cannot recover the session by calling session_start(),
115 * so we still want to call it. In this case, though, we want to avoid session_start() to send any
116 * headers at all so that no error is generated, so we clear the cache limiter temporarily (no headers
117 * sent then) and restore it after successfully starting the session.
118 */
119 session_cache_limiter('');
120 }
121 session_cache_limiter($cacheLimiter);
122 @session_start();
123 }
124
125
136 public function restorePrevious()
137 {
138 if (empty($this->previous_session)) {
139 return; // nothing to do here
140 }
141
142 // close our own session
143 session_write_close();
144
145 session_name($this->previous_session['name']);
146 session_set_cookie_params(
147 $this->previous_session['cookie_params']['lifetime'],
148 $this->previous_session['cookie_params']['path'],
149 $this->previous_session['cookie_params']['domain'],
150 $this->previous_session['cookie_params']['secure'],
151 $this->previous_session['cookie_params']['httponly']
152 );
153 session_id($this->previous_session['id']);
154 $this->previous_session = array();
155 $this->sessionStart();
156
157 /*
158 * At this point, we have restored a previously-existing session, so we can't continue to use our session here.
159 * Therefore, we need to load our session again in case we need it. We remove this handler from the parent
160 * class so that the handler is initialized again if we ever need to do something with the session.
161 */
162 parent::$sessionHandler = null;
163 }
164
165
171 public function newSessionId()
172 {
173 // generate new (secure) session id
174 $sessionId = bin2hex(openssl_random_pseudo_bytes(16));
176
177 return $sessionId;
178 }
179
180
188 public function getCookieSessionId()
189 {
190 if (!self::hasSessionCookie()) {
191 return null; // there's no session cookie, can't return ID
192 }
193
194 // do not rely on session_id() as it can return the ID of a previous session. Get it from the cookie instead.
195 session_id($_COOKIE[$this->cookie_name]);
196
197 $session_cookie_params = session_get_cookie_params();
198
199 if ($session_cookie_params['secure'] && !HTTP::isHTTPS()) {
200 throw new \SimpleSAML_Error_Exception('Session start with secure cookie not allowed on http.');
201 }
202
203 $this->sessionStart();
204 return session_id();
205 }
206
207
213 public function getSessionCookieName()
214 {
215 return $this->cookie_name;
216 }
217
218
225 {
226 $_SESSION['SimpleSAMLphp_SESSION'] = serialize($session);
227 }
228
229
240 public function loadSession($sessionId = null)
241 {
242 assert('is_string($sessionId) || is_null($sessionId)');
243
244 if ($sessionId !== null) {
245 if (session_id() === '') {
246 // session not initiated with getCookieSessionId(), start session without setting cookie
247 $ret = ini_set('session.use_cookies', '0');
248 if ($ret === false) {
249 throw new \SimpleSAML_Error_Exception('Disabling PHP option session.use_cookies failed.');
250 }
251
252 session_id($sessionId);
253 $this->sessionStart();
254 } elseif ($sessionId !== session_id()) {
255 throw new \SimpleSAML_Error_Exception('Cannot load PHP session with a specific ID.');
256 }
257 } elseif (session_id() === '') {
258 self::getCookieSessionId();
259 }
260
261 if (!isset($_SESSION['SimpleSAMLphp_SESSION'])) {
262 return null;
263 }
264
265 $session = $_SESSION['SimpleSAMLphp_SESSION'];
266 assert('is_string($session)');
267
268 $session = unserialize($session);
269
270 return ($session !== false) ? $session : null;
271 }
272
273
281 public function hasSessionCookie()
282 {
283 return array_key_exists($this->cookie_name, $_COOKIE);
284 }
285
286
298 public function getCookieParams()
299 {
301
302 $ret = parent::getCookieParams();
303
304 if ($config->hasValue('session.phpsession.limitedpath') && $config->hasValue('session.cookie.path')) {
305 throw new \SimpleSAML_Error_Exception(
306 'You cannot set both the session.phpsession.limitedpath and session.cookie.path options.'
307 );
308 } elseif ($config->hasValue('session.phpsession.limitedpath')) {
309 $ret['path'] = $config->getBoolean(
310 'session.phpsession.limitedpath',
311 false
312 ) ? $config->getBasePath() : '/';
313 }
314
315 $ret['httponly'] = $config->getBoolean('session.phpsession.httponly', true);
316
317 return $ret;
318 }
319
320
330 public function setCookie($sessionName, $sessionID, array $cookieParams = null)
331 {
332 if ($cookieParams === null) {
333 $cookieParams = session_get_cookie_params();
334 }
335
336 if ($cookieParams['secure'] && !HTTP::isHTTPS()) {
337 throw new CannotSetCookie(
338 'Setting secure cookie on plain HTTP is not allowed.',
339 CannotSetCookie::SECURE_COOKIE
340 );
341 }
342
343 if (headers_sent()) {
344 throw new CannotSetCookie(
345 'Headers already sent.',
346 CannotSetCookie::HEADERS_SENT
347 );
348 }
349
350 session_set_cookie_params(
351 $cookieParams['lifetime'],
352 $cookieParams['path'],
353 $cookieParams['domain'],
354 $cookieParams['secure'],
355 $cookieParams['httponly']
356 );
357
358 if (session_id() !== '') {
359 // session already started, close it
360 session_write_close();
361 }
362
363 session_id($sessionID);
364 $this->sessionStart();
365 }
366}
$_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:418
Attribute-related utility methods.
$ret
Definition: parser.php:6
defined( 'APPLICATION_ENV')||define( 'APPLICATION_ENV'
Definition: bootstrap.php:27
$session
$sessionID
$params
Definition: disable.php:11