wp/wp-includes/class-wp-session-tokens.php
changeset 7 cf61fcea0001
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
       
     1 <?php
       
     2 /**
       
     3  * Session API: WP_Session_Tokens class
       
     4  *
       
     5  * @package WordPress
       
     6  * @subpackage Session
       
     7  * @since 4.7.0
       
     8  */
       
     9 
       
    10 /**
       
    11  * Abstract class for managing user session tokens.
       
    12  *
       
    13  * @since 4.0.0
       
    14  */
       
    15 abstract class WP_Session_Tokens {
       
    16 
       
    17 	/**
       
    18 	 * User ID.
       
    19 	 *
       
    20 	 * @since 4.0.0
       
    21 	 * @var int User ID.
       
    22 	 */
       
    23 	protected $user_id;
       
    24 
       
    25 	/**
       
    26 	 * Protected constructor.
       
    27 	 *
       
    28 	 * @since 4.0.0
       
    29 	 *
       
    30 	 * @param int $user_id User whose session to manage.
       
    31 	 */
       
    32 	protected function __construct( $user_id ) {
       
    33 		$this->user_id = $user_id;
       
    34 	}
       
    35 
       
    36 	/**
       
    37 	 * Retrieves a session token manager instance for a user.
       
    38 	 *
       
    39 	 * This method contains a {@see 'session_token_manager'} filter, allowing a plugin to swap out
       
    40 	 * the session manager for a subclass of `WP_Session_Tokens`.
       
    41 	 *
       
    42 	 * @since 4.0.0
       
    43 	 * @static
       
    44 	 *
       
    45 	 * @param int $user_id User whose session to manage.
       
    46 	 * @return WP_User_Meta_Session_Tokens WP_User_Meta_Session_Tokens class instance by default.
       
    47 	 */
       
    48 	final public static function get_instance( $user_id ) {
       
    49 		/**
       
    50 		 * Filters the session token manager used.
       
    51 		 *
       
    52 		 * @since 4.0.0
       
    53 		 *
       
    54 		 * @param string $session Name of class to use as the manager.
       
    55 		 *                        Default 'WP_User_Meta_Session_Tokens'.
       
    56 		 */
       
    57 		$manager = apply_filters( 'session_token_manager', 'WP_User_Meta_Session_Tokens' );
       
    58 		return new $manager( $user_id );
       
    59 	}
       
    60 
       
    61 	/**
       
    62 	 * Hashes a session token for storage.
       
    63 	 *
       
    64 	 * @since 4.0.0
       
    65 	 *
       
    66 	 * @param string $token Session token to hash.
       
    67 	 * @return string A hash of the session token (a verifier).
       
    68 	 */
       
    69 	final private function hash_token( $token ) {
       
    70 		// If ext/hash is not present, use sha1() instead.
       
    71 		if ( function_exists( 'hash' ) ) {
       
    72 			return hash( 'sha256', $token );
       
    73 		} else {
       
    74 			return sha1( $token );
       
    75 		}
       
    76 	}
       
    77 
       
    78 	/**
       
    79 	 * Get a user's session.
       
    80 	 *
       
    81 	 * @since 4.0.0
       
    82 	 *
       
    83 	 * @param string $token Session token
       
    84 	 * @return array User session
       
    85 	 */
       
    86 	final public function get( $token ) {
       
    87 		$verifier = $this->hash_token( $token );
       
    88 		return $this->get_session( $verifier );
       
    89 	}
       
    90 
       
    91 	/**
       
    92 	 * Validate a user's session token as authentic.
       
    93 	 *
       
    94 	 * Checks that the given token is present and hasn't expired.
       
    95 	 *
       
    96 	 * @since 4.0.0
       
    97 	 *
       
    98 	 * @param string $token Token to verify.
       
    99 	 * @return bool Whether the token is valid for the user.
       
   100 	 */
       
   101 	final public function verify( $token ) {
       
   102 		$verifier = $this->hash_token( $token );
       
   103 		return (bool) $this->get_session( $verifier );
       
   104 	}
       
   105 
       
   106 	/**
       
   107 	 * Generate a session token and attach session information to it.
       
   108 	 *
       
   109 	 * A session token is a long, random string. It is used in a cookie
       
   110 	 * link that cookie to an expiration time and to ensure the cookie
       
   111 	 * becomes invalidated upon logout.
       
   112 	 *
       
   113 	 * This function generates a token and stores it with the associated
       
   114 	 * expiration time (and potentially other session information via the
       
   115 	 * {@see 'attach_session_information'} filter).
       
   116 	 *
       
   117 	 * @since 4.0.0
       
   118 	 *
       
   119 	 * @param int $expiration Session expiration timestamp.
       
   120 	 * @return string Session token.
       
   121 	 */
       
   122 	final public function create( $expiration ) {
       
   123 		/**
       
   124 		 * Filters the information attached to the newly created session.
       
   125 		 *
       
   126 		 * Could be used in the future to attach information such as
       
   127 		 * IP address or user agent to a session.
       
   128 		 *
       
   129 		 * @since 4.0.0
       
   130 		 *
       
   131 		 * @param array $session Array of extra data.
       
   132 		 * @param int   $user_id User ID.
       
   133 		 */
       
   134 		$session = apply_filters( 'attach_session_information', array(), $this->user_id );
       
   135 		$session['expiration'] = $expiration;
       
   136 
       
   137 		// IP address.
       
   138 		if ( !empty( $_SERVER['REMOTE_ADDR'] ) ) {
       
   139 			$session['ip'] = $_SERVER['REMOTE_ADDR'];
       
   140 		}
       
   141 
       
   142 		// User-agent.
       
   143 		if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
       
   144 			$session['ua'] = wp_unslash( $_SERVER['HTTP_USER_AGENT'] );
       
   145 		}
       
   146 
       
   147 		// Timestamp
       
   148 		$session['login'] = time();
       
   149 
       
   150 		$token = wp_generate_password( 43, false, false );
       
   151 
       
   152 		$this->update( $token, $session );
       
   153 
       
   154 		return $token;
       
   155 	}
       
   156 
       
   157 	/**
       
   158 	 * Update a session token.
       
   159 	 *
       
   160 	 * @since 4.0.0
       
   161 	 *
       
   162 	 * @param string $token Session token to update.
       
   163 	 * @param array  $session Session information.
       
   164 	 */
       
   165 	final public function update( $token, $session ) {
       
   166 		$verifier = $this->hash_token( $token );
       
   167 		$this->update_session( $verifier, $session );
       
   168 	}
       
   169 
       
   170 	/**
       
   171 	 * Destroy a session token.
       
   172 	 *
       
   173 	 * @since 4.0.0
       
   174 	 *
       
   175 	 * @param string $token Session token to destroy.
       
   176 	 */
       
   177 	final public function destroy( $token ) {
       
   178 		$verifier = $this->hash_token( $token );
       
   179 		$this->update_session( $verifier, null );
       
   180 	}
       
   181 
       
   182 	/**
       
   183 	 * Destroy all session tokens for this user,
       
   184 	 * except a single token, presumably the one in use.
       
   185 	 *
       
   186 	 * @since 4.0.0
       
   187 	 *
       
   188 	 * @param string $token_to_keep Session token to keep.
       
   189 	 */
       
   190 	final public function destroy_others( $token_to_keep ) {
       
   191 		$verifier = $this->hash_token( $token_to_keep );
       
   192 		$session = $this->get_session( $verifier );
       
   193 		if ( $session ) {
       
   194 			$this->destroy_other_sessions( $verifier );
       
   195 		} else {
       
   196 			$this->destroy_all_sessions();
       
   197 		}
       
   198 	}
       
   199 
       
   200 	/**
       
   201 	 * Determine whether a session token is still valid,
       
   202 	 * based on expiration.
       
   203 	 *
       
   204 	 * @since 4.0.0
       
   205 	 *
       
   206 	 * @param array $session Session to check.
       
   207 	 * @return bool Whether session is valid.
       
   208 	 */
       
   209 	final protected function is_still_valid( $session ) {
       
   210 		return $session['expiration'] >= time();
       
   211 	}
       
   212 
       
   213 	/**
       
   214 	 * Destroy all session tokens for a user.
       
   215 	 *
       
   216 	 * @since 4.0.0
       
   217 	 */
       
   218 	final public function destroy_all() {
       
   219 		$this->destroy_all_sessions();
       
   220 	}
       
   221 
       
   222 	/**
       
   223 	 * Destroy all session tokens for all users.
       
   224 	 *
       
   225 	 * @since 4.0.0
       
   226 	 * @static
       
   227 	 */
       
   228 	final public static function destroy_all_for_all_users() {
       
   229 		/** This filter is documented in wp-includes/class-wp-session-tokens.php */
       
   230 		$manager = apply_filters( 'session_token_manager', 'WP_User_Meta_Session_Tokens' );
       
   231 		call_user_func( array( $manager, 'drop_sessions' ) );
       
   232 	}
       
   233 
       
   234 	/**
       
   235 	 * Retrieve all sessions of a user.
       
   236 	 *
       
   237 	 * @since 4.0.0
       
   238 	 *
       
   239 	 * @return array Sessions of a user.
       
   240 	 */
       
   241 	final public function get_all() {
       
   242 		return array_values( $this->get_sessions() );
       
   243 	}
       
   244 
       
   245 	/**
       
   246 	 * This method should retrieve all sessions of a user, keyed by verifier.
       
   247 	 *
       
   248 	 * @since 4.0.0
       
   249 	 *
       
   250 	 * @return array Sessions of a user, keyed by verifier.
       
   251 	 */
       
   252 	abstract protected function get_sessions();
       
   253 
       
   254 	/**
       
   255 	 * This method should look up a session by its verifier (token hash).
       
   256 	 *
       
   257 	 * @since 4.0.0
       
   258 	 *
       
   259 	 * @param string $verifier Verifier of the session to retrieve.
       
   260 	 * @return array|null The session, or null if it does not exist.
       
   261 	 */
       
   262 	abstract protected function get_session( $verifier );
       
   263 
       
   264 	/**
       
   265 	 * This method should update a session by its verifier.
       
   266 	 *
       
   267 	 * Omitting the second argument should destroy the session.
       
   268 	 *
       
   269 	 * @since 4.0.0
       
   270 	 *
       
   271 	 * @param string $verifier Verifier of the session to update.
       
   272 	 * @param array  $session  Optional. Session. Omitting this argument destroys the session.
       
   273 	 */
       
   274 	abstract protected function update_session( $verifier, $session = null );
       
   275 
       
   276 	/**
       
   277 	 * This method should destroy all session tokens for this user,
       
   278 	 * except a single session passed.
       
   279 	 *
       
   280 	 * @since 4.0.0
       
   281 	 *
       
   282 	 * @param string $verifier Verifier of the session to keep.
       
   283 	 */
       
   284 	abstract protected function destroy_other_sessions( $verifier );
       
   285 
       
   286 	/**
       
   287 	 * This method should destroy all sessions for a user.
       
   288 	 *
       
   289 	 * @since 4.0.0
       
   290 	 */
       
   291 	abstract protected function destroy_all_sessions();
       
   292 
       
   293 	/**
       
   294 	 * This static method should destroy all session tokens for all users.
       
   295 	 *
       
   296 	 * @since 4.0.0
       
   297 	 * @static
       
   298 	 */
       
   299 	public static function drop_sessions() {}
       
   300 }