wallabag/inc/Session.class.php
2013-04-19 11:41:12 +02:00

136 lines
4.5 KiB
PHP

<?php
/**
* Session management class
* http://www.developpez.net/forums/d51943/php/langage/sessions/
* http://sebsauvage.net/wiki/doku.php?id=php:session
* http://sebsauvage.net/wiki/doku.php?id=php:shaarli
*
* Features:
* - Everything is stored on server-side (we do not trust client-side data,
* such as cookie expiration)
* - IP addresses + user agent are checked on each access to prevent session
* cookie hijacking (such as Firesheep)
* - Session expires on user inactivity (Session expiration date is
* automatically updated everytime the user accesses a page.)
* - A unique secret key is generated on server-side for this session
* (and never sent over the wire) which can be used
* to sign forms (HMAC) (See $_SESSION['uid'] )
* - Token management to prevent XSRF attacks.
*
* TODO:
* - log login fail
* - prevent brute force (ban IP)
*
* HOWTOUSE:
* - Just call Session::init(); to initialize session and
* check if connected with Session::isLogged()
*/
class Session
{
// If the user does not access any page within this time,
// his/her session is considered expired (in seconds).
public static $inactivity_timeout = 3600;
private static $_instance;
// constructor
private function __construct()
{
// Use cookies to store session.
ini_set('session.use_cookies', 1);
// Force cookies for session (phpsessionID forbidden in URL)
ini_set('session.use_only_cookies', 1);
if (!session_id()){
// Prevent php to use sessionID in URL if cookies are disabled.
ini_set('session.use_trans_sid', false);
session_start('poche');
}
}
// initialize session
public static function init()
{
if (!isset(self::$_instance)) {
self::$_instance = new Session();
}
}
// Returns the IP address, user agent and language of the client
// (Used to prevent session cookie hijacking.)
private static function _allInfos()
{
$infos = $_SERVER["REMOTE_ADDR"];
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$infos.=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
if (isset($_SERVER['HTTP_CLIENT_IP'])) {
$infos.='_'.$_SERVER['HTTP_CLIENT_IP'];
}
$infos.='_'.$_SERVER['HTTP_USER_AGENT'];
$infos.='_'.$_SERVER['HTTP_ACCEPT_LANGUAGE'];
return sha1($infos);
}
// Check that user/password is correct and init some SESSION variables.
public static function login($login,$password,$login_test,$password_test,
$pValues = array())
{
foreach ($pValues as $key => $value) {
$_SESSION[$key] = $value;
}
if ($login==$login_test && $password==$password_test){
// generate unique random number to sign forms (HMAC)
$_SESSION['uid'] = sha1(uniqid('',true).'_'.mt_rand());
$_SESSION['info']=Session::_allInfos();
$_SESSION['username']=$login;
// Set session expiration.
$_SESSION['expires_on']=time()+Session::$inactivity_timeout;
return true;
}
return false;
}
// Force logout
public static function logout()
{
unset($_SESSION['uid'],$_SESSION['info'],$_SESSION['expires_on'],$_SESSION['tokens']);
}
// Make sure user is logged in.
public static function isLogged()
{
if (!isset ($_SESSION['uid'])
|| $_SESSION['info']!=Session::_allInfos()
|| time()>=$_SESSION['expires_on']){
Session::logout();
return false;
}
// User accessed a page : Update his/her session expiration date.
$_SESSION['expires_on']=time()+Session::$inactivity_timeout;
return true;
}
// Returns a token.
public static function getToken()
{
if (!isset($_SESSION['tokens'])){
$_SESSION['tokens']=array();
}
// We generate a random string and store it on the server side.
$rnd = sha1(uniqid('',true).'_'.mt_rand());
$_SESSION['tokens'][$rnd]=1;
return $rnd;
}
// Tells if a token is ok. Using this function will destroy the token.
// return true if token is ok.
public static function isToken($token)
{
if (isset($_SESSION['tokens'][$token]))
{
unset($_SESSION['tokens'][$token]); // Token is used: destroy it.
return true; // Token is ok.
}
return false; // Wrong token, or already used.
}
}