24 * 3600 * 14 // 14 days ]); session_start(); // Resuming an existing session? Check what we know! if (isset($_SESSION['user_id'], $_SESSION['ip_address'], $_SESSION['user_agent'])) { // If we're not browsing over HTTPS, protect against session hijacking. if (!isset($_SERVER['HTTPS']) && isset($_SERVER['REMOTE_ADDR']) && $_SESSION['ip_address'] !== $_SERVER['REMOTE_ADDR']) { $_SESSION = []; Dispatcher::kickGuest('Your session failed to validate', 'Your IP address has changed. Please re-login and try again.'); } // Either way, require re-login if the browser identifier has changed. elseif (isset($_SERVER['HTTP_USER_AGENT']) && $_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT']) { $_SESSION = []; Dispatcher::kickGuest('Your session failed to validate', 'Your browser identifier has changed. Please re-login and try again.'); } } elseif (!isset($_SESSION['ip_address'], $_SESSION['user_agent'])) $_SESSION = [ 'ip_address' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '', 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '', ]; return true; } public static function resetSessionToken() { $_SESSION['session_token'] = sha1(session_id() . mt_rand()); $_SESSION['session_token_key'] = substr(preg_replace('~^\d+~', '', sha1(mt_rand() . session_id() . mt_rand())), 0, rand(7, 12)); return true; } public static function validateSession($method = 'post') { // First, check whether the submitted token and key match the ones in storage. if (($method === 'post' && (!isset($_POST[$_SESSION['session_token_key']]) || $_POST[$_SESSION['session_token_key']] !== $_SESSION['session_token'])) || ($method === 'get' && (!isset($_GET[$_SESSION['session_token_key']]) || $_GET[$_SESSION['session_token_key']] !== $_SESSION['session_token']))) throw new UserFacingException('Session failed to verify (' . $method . '). Please reload the page and try again.'); // Check the referring site, too -- should be the same site! $referring_host = isset($_SERVER['HTTP_REFERER']) ? parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) : ''; if (!empty($referring_host)) { if (strpos($_SERVER['HTTP_HOST'], ':') !== false) $current_host = substr($_SERVER['HTTP_HOST'], 0, strpos($_SERVER['HTTP_HOST'], ':')); else $current_host = $_SERVER['HTTP_HOST']; $base_url_host = parse_url(BASEURL, PHP_URL_HOST); // The referring_host must match either the base_url_host or the current_host. if (strtolower($referring_host) !== strtolower($base_url_host) && strtolower($referring_host) !== strtolower($current_host)) throw new UserFacingException('Invalid referring URL. Please reload the page and try again.'); } // All looks good from here! But you can only use this token once, so... return self::resetSessionToken(); } public static function getSessionToken() { if (empty($_SESSION['session_token'])) trigger_error('Call to getSessionToken without a session token being set!', E_USER_ERROR); return $_SESSION['session_token']; } public static function getSessionTokenKey() { if (empty($_SESSION['session_token_key'])) trigger_error('Call to getSessionTokenKey without a session token key being set!', E_USER_ERROR); return $_SESSION['session_token_key']; } }