Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- *
- * Author: Juan Pablo Guereca.
- *
- * Storeless user's session system.
- *
- * Interface:
- *
- * create( <id_user>, <remember_me> )
- *
- * is_alive(): returns false or the id_user
- *
- * destroy(): it just remove the session cookie, the session can't be destroyed, it just expires.
- *
- */
- class Session {
- const SESSION_PASSWORD_PREVIOUS = \SESSION_PASSWORD_PREVIOUS;
- const SESSION_PASSWORD_CURRENT = \SESSION_PASSWORD_CURRENT;
- private static $id_user = 0;
- private static $remember_me = false;
- private static $last_visit_time = 0;
- private static $is_alive = false;
- private static $hash_with_previous_password = false;
- const SESSION_ID_NAME = 's';
- const SESSION_ID_VALUE = '%d,%d,%d,%s';
- const SESSION_TIME_FRAME_SECONDS = 180; // 3 Minutes
- const REMEMBER_ME_EXPIRICY_DAYS = 7; // 1 week of remember me.
- const NOT_REMEMBER_ME_EXPIRICY_MINUTES = 15;
- private function __construct( ) { }
- public static function create ( $id_user, $remember_me = false ) {
- //The only way to "erase" a session is setting its id_user in the gobal $BANNED_ID_USER_SESSION.
- //If the id_user is set we return false.
- if( isset( $GLOBALS['BANNED_SESSION_ID_USERS'] ) && isset( $GLOBALS['BANNED_SESSION_ID_USERS'][$id_user] ) ) {
- return false;
- }
- $last_visit_time = \time();
- $session_hash = self::build_session_hash( $id_user, $last_visit_time, $remember_me === true ? '1' : '0', self::SESSION_PASSWORD_CURRENT );
- \lib\set_cookie( self::SESSION_ID_NAME, sprintf( self::SESSION_ID_VALUE, $id_user, $remember_me , $last_visit_time, $session_hash ), $remember_me === true ? REMEMBER_ME_EXPIRICY_DAYS : null );
- self::$id_user = $id_user;
- self::$is_alive = true;
- }
- public static function is_alive() {
- if( self::$is_alive ) {
- return self::$is_alive;
- }
- if ( ! isset( $_COOKIE[ self::SESSION_ID_NAME ] ) ) {
- self::$is_alive = false;
- return false;
- }
- list( $id_user, $remember_me , $last_visit_time, $session_hash ) = explode( ',', $_COOKIE[ self::SESSION_ID_NAME ] );
- //The only way to "erase" a session is setting its id_user in the gobal $BANNED_ID_USER_SESSION.
- //If the id_user is set we return false.
- if( isset( $GLOBALS['BANNED_SESSION_ID_USERS'] ) && isset( $GLOBALS['BANNED_SESSION_ID_USERS'][$id_user] ) ) {
- return false;
- }
- $hash_current_session_password = self::build_session_hash( $id_user, $last_visit_time, $remember_me, self::SESSION_PASSWORD_CURRENT );
- if( $session_hash !== $hash_current_session_password ) {
- /**
- * After changing the session password the users have hashes generated with the previous password
- * so we check if it match the hash with the previous session password.
- * If it does, we regenerate the hash with the new session password.
- */
- $hash_previous_session_password = self::build_session_hash( $id_user, $last_visit_time, $remember_me, self::SESSION_PASSWORD_PREVIOUS );
- if( $session_hash === $hash_previous_session_password ) {
- /**
- * The user has a session generated with the previous password.
- * That's ok but lets set the "hash with previous password" so the keep_alive method
- * regenerates the session hash with the new password.
- */
- self::$hash_with_previous_password = True;
- } else {
- //This would be a hack attempt
- self::destroy();
- self::$is_alive = false;
- return false;
- }
- }
- //Checking if it has expired
- if( $remember_me === '1' ) {
- $max_time = self::REMEMBER_ME_EXPIRICY_DAYS * 86400;
- } else {
- $max_time = self::NOT_REMEMBER_ME_EXPIRICY_MINUTES * 60;
- }
- self::$last_visit_time = (int) $last_visit_time;
- if( ( self::$last_visit_time + $max_time ) < \time() ) {
- //It has expired
- self::destroy();
- self::$is_alive = false;
- return false;
- }
- self::$is_alive = true;
- self::$id_user = $id_user;
- self::$remember_me = $remember_me === '1' ? true : false;
- return true;
- }
- public static function keep_alive() {
- if( self::$is_alive ) {
- //With time frames we avoid setting a new session cookie each request
- $ts = time();
- $current_time_frame = $ts - ( $ts % self::SESSION_TIME_FRAME_SECONDS );
- $last_visit_time_frame = self::$last_visit_time - ( self::$last_visit_time % self::SESSION_TIME_FRAME_SECONDS );
- if( $current_time_frame !== $last_visit_time_frame || self::$hash_with_previous_password ) {
- self::create( self::$id_user, self::$remember_me );
- }
- }
- }
- public static function destroy() {
- //The session can't really be destroyed because it's not stored.
- //It's just not usable after the expiricy time.
- //All we can do is remove the cookie.
- \lib\delete_cookie( self::SESSION_ID_NAME );
- }
- public static function get_id_user() {
- return self::$id_user;
- }
- private static function build_session_hash( $id_user, $last_visit_time, $remember_me, $session_password ) {
- list( $ip_first_octect ) = \explode( '.', $_SERVER['REMOTE_ADDR'] );
- $user_agent = $_SERVER['HTTP_USER_AGENT'];
- return \lib\sha256( $session_password . $id_user . $last_visit_time . $remember_me . $user_agent . $ip_first_octect );
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement