Changeset 38353 for trunk/src/wp-includes/session.php
- Timestamp:
- 08/25/2016 05:43:41 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/session.php
r37544 r38353 1 1 <?php 2 2 /** 3 * Abstract class for managing user session tokens.3 * Session API 4 4 * 5 5 * @since 4.0.0 6 6 */ 7 abstract class WP_Session_Tokens {8 7 9 /** 10 * User ID. 11 * 12 * @since 4.0.0 13 * @access protected 14 * @var int User ID. 15 */ 16 protected $user_id; 17 18 /** 19 * Protected constructor. 20 * 21 * @since 4.0.0 22 * 23 * @param int $user_id User whose session to manage. 24 */ 25 protected function __construct( $user_id ) { 26 $this->user_id = $user_id; 27 } 28 29 /** 30 * Get a session token manager instance for a user. 31 * 32 * This method contains a filter that allows a plugin to swap out 33 * the session manager for a subclass of WP_Session_Tokens. 34 * 35 * @since 4.0.0 36 * @access public 37 * @static 38 * 39 * @param int $user_id User whose session to manage. 40 */ 41 final public static function get_instance( $user_id ) { 42 /** 43 * Filters the session token manager used. 44 * 45 * @since 4.0.0 46 * 47 * @param string $session Name of class to use as the manager. 48 * Default 'WP_User_Meta_Session_Tokens'. 49 */ 50 $manager = apply_filters( 'session_token_manager', 'WP_User_Meta_Session_Tokens' ); 51 return new $manager( $user_id ); 52 } 53 54 /** 55 * Hashes a session token for storage. 56 * 57 * @since 4.0.0 58 * @access private 59 * 60 * @param string $token Session token to hash. 61 * @return string A hash of the session token (a verifier). 62 */ 63 final private function hash_token( $token ) { 64 // If ext/hash is not present, use sha1() instead. 65 if ( function_exists( 'hash' ) ) { 66 return hash( 'sha256', $token ); 67 } else { 68 return sha1( $token ); 69 } 70 } 71 72 /** 73 * Get a user's session. 74 * 75 * @since 4.0.0 76 * @access public 77 * 78 * @param string $token Session token 79 * @return array User session 80 */ 81 final public function get( $token ) { 82 $verifier = $this->hash_token( $token ); 83 return $this->get_session( $verifier ); 84 } 85 86 /** 87 * Validate a user's session token as authentic. 88 * 89 * Checks that the given token is present and hasn't expired. 90 * 91 * @since 4.0.0 92 * @access public 93 * 94 * @param string $token Token to verify. 95 * @return bool Whether the token is valid for the user. 96 */ 97 final public function verify( $token ) { 98 $verifier = $this->hash_token( $token ); 99 return (bool) $this->get_session( $verifier ); 100 } 101 102 /** 103 * Generate a session token and attach session information to it. 104 * 105 * A session token is a long, random string. It is used in a cookie 106 * link that cookie to an expiration time and to ensure the cookie 107 * becomes invalidated upon logout. 108 * 109 * This function generates a token and stores it with the associated 110 * expiration time (and potentially other session information via the 111 * {@see 'attach_session_information'} filter). 112 * 113 * @since 4.0.0 114 * @access public 115 * 116 * @param int $expiration Session expiration timestamp. 117 * @return string Session token. 118 */ 119 final public function create( $expiration ) { 120 /** 121 * Filters the information attached to the newly created session. 122 * 123 * Could be used in the future to attach information such as 124 * IP address or user agent to a session. 125 * 126 * @since 4.0.0 127 * 128 * @param array $session Array of extra data. 129 * @param int $user_id User ID. 130 */ 131 $session = apply_filters( 'attach_session_information', array(), $this->user_id ); 132 $session['expiration'] = $expiration; 133 134 // IP address. 135 if ( !empty( $_SERVER['REMOTE_ADDR'] ) ) { 136 $session['ip'] = $_SERVER['REMOTE_ADDR']; 137 } 138 139 // User-agent. 140 if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) { 141 $session['ua'] = wp_unslash( $_SERVER['HTTP_USER_AGENT'] ); 142 } 143 144 // Timestamp 145 $session['login'] = time(); 146 147 $token = wp_generate_password( 43, false, false ); 148 149 $this->update( $token, $session ); 150 151 return $token; 152 } 153 154 /** 155 * Update a session token. 156 * 157 * @since 4.0.0 158 * @access public 159 * 160 * @param string $token Session token to update. 161 * @param array $session Session information. 162 */ 163 final public function update( $token, $session ) { 164 $verifier = $this->hash_token( $token ); 165 $this->update_session( $verifier, $session ); 166 } 167 168 /** 169 * Destroy a session token. 170 * 171 * @since 4.0.0 172 * @access public 173 * 174 * @param string $token Session token to destroy. 175 */ 176 final public function destroy( $token ) { 177 $verifier = $this->hash_token( $token ); 178 $this->update_session( $verifier, null ); 179 } 180 181 /** 182 * Destroy all session tokens for this user, 183 * except a single token, presumably the one in use. 184 * 185 * @since 4.0.0 186 * @access public 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 * @access protected 206 * 207 * @param array $session Session to check. 208 * @return bool Whether session is valid. 209 */ 210 final protected function is_still_valid( $session ) { 211 return $session['expiration'] >= time(); 212 } 213 214 /** 215 * Destroy all session tokens for a user. 216 * 217 * @since 4.0.0 218 * @access public 219 */ 220 final public function destroy_all() { 221 $this->destroy_all_sessions(); 222 } 223 224 /** 225 * Destroy all session tokens for all users. 226 * 227 * @since 4.0.0 228 * @access public 229 * @static 230 */ 231 final public static function destroy_all_for_all_users() { 232 $manager = apply_filters( 'session_token_manager', 'WP_User_Meta_Session_Tokens' ); 233 call_user_func( array( $manager, 'drop_sessions' ) ); 234 } 235 236 /** 237 * Retrieve all sessions of a user. 238 * 239 * @since 4.0.0 240 * @access public 241 * 242 * @return array Sessions of a user. 243 */ 244 final public function get_all() { 245 return array_values( $this->get_sessions() ); 246 } 247 248 /** 249 * This method should retrieve all sessions of a user, keyed by verifier. 250 * 251 * @since 4.0.0 252 * @access protected 253 * 254 * @return array Sessions of a user, keyed by verifier. 255 */ 256 abstract protected function get_sessions(); 257 258 /** 259 * This method should look up a session by its verifier (token hash). 260 * 261 * @since 4.0.0 262 * @access protected 263 * 264 * @param string $verifier Verifier of the session to retrieve. 265 * @return array|null The session, or null if it does not exist. 266 */ 267 abstract protected function get_session( $verifier ); 268 269 /** 270 * This method should update a session by its verifier. 271 * 272 * Omitting the second argument should destroy the session. 273 * 274 * @since 4.0.0 275 * @access protected 276 * 277 * @param string $verifier Verifier of the session to update. 278 * @param array $session Optional. Session. Omitting this argument destroys the session. 279 */ 280 abstract protected function update_session( $verifier, $session = null ); 281 282 /** 283 * This method should destroy all session tokens for this user, 284 * except a single session passed. 285 * 286 * @since 4.0.0 287 * @access protected 288 * 289 * @param string $verifier Verifier of the session to keep. 290 */ 291 abstract protected function destroy_other_sessions( $verifier ); 292 293 /** 294 * This method should destroy all sessions for a user. 295 * 296 * @since 4.0.0 297 * @access protected 298 */ 299 abstract protected function destroy_all_sessions(); 300 301 /** 302 * This static method should destroy all session tokens for all users. 303 * 304 * @since 4.0.0 305 * @access public 306 * @static 307 */ 308 public static function drop_sessions() {} 309 } 310 311 /** 312 * Meta-based user sessions token manager. 313 * 314 * @since 4.0.0 315 */ 316 class WP_User_Meta_Session_Tokens extends WP_Session_Tokens { 317 318 /** 319 * Get all sessions of a user. 320 * 321 * @since 4.0.0 322 * @access protected 323 * 324 * @return array Sessions of a user. 325 */ 326 protected function get_sessions() { 327 $sessions = get_user_meta( $this->user_id, 'session_tokens', true ); 328 329 if ( ! is_array( $sessions ) ) { 330 return array(); 331 } 332 333 $sessions = array_map( array( $this, 'prepare_session' ), $sessions ); 334 return array_filter( $sessions, array( $this, 'is_still_valid' ) ); 335 } 336 337 /** 338 * Converts an expiration to an array of session information. 339 * 340 * @param mixed $session Session or expiration. 341 * @return array Session. 342 */ 343 protected function prepare_session( $session ) { 344 if ( is_int( $session ) ) { 345 return array( 'expiration' => $session ); 346 } 347 348 return $session; 349 } 350 351 /** 352 * Retrieve a session by its verifier (token hash). 353 * 354 * @since 4.0.0 355 * @access protected 356 * 357 * @param string $verifier Verifier of the session to retrieve. 358 * @return array|null The session, or null if it does not exist 359 */ 360 protected function get_session( $verifier ) { 361 $sessions = $this->get_sessions(); 362 363 if ( isset( $sessions[ $verifier ] ) ) { 364 return $sessions[ $verifier ]; 365 } 366 367 return null; 368 } 369 370 /** 371 * Update a session by its verifier. 372 * 373 * @since 4.0.0 374 * @access protected 375 * 376 * @param string $verifier Verifier of the session to update. 377 * @param array $session Optional. Session. Omitting this argument destroys the session. 378 */ 379 protected function update_session( $verifier, $session = null ) { 380 $sessions = $this->get_sessions(); 381 382 if ( $session ) { 383 $sessions[ $verifier ] = $session; 384 } else { 385 unset( $sessions[ $verifier ] ); 386 } 387 388 $this->update_sessions( $sessions ); 389 } 390 391 /** 392 * Update a user's sessions in the usermeta table. 393 * 394 * @since 4.0.0 395 * @access protected 396 * 397 * @param array $sessions Sessions. 398 */ 399 protected function update_sessions( $sessions ) { 400 if ( $sessions ) { 401 update_user_meta( $this->user_id, 'session_tokens', $sessions ); 402 } else { 403 delete_user_meta( $this->user_id, 'session_tokens' ); 404 } 405 } 406 407 /** 408 * Destroy all session tokens for a user, except a single session passed. 409 * 410 * @since 4.0.0 411 * @access protected 412 * 413 * @param string $verifier Verifier of the session to keep. 414 */ 415 protected function destroy_other_sessions( $verifier ) { 416 $session = $this->get_session( $verifier ); 417 $this->update_sessions( array( $verifier => $session ) ); 418 } 419 420 /** 421 * Destroy all session tokens for a user. 422 * 423 * @since 4.0.0 424 * @access protected 425 */ 426 protected function destroy_all_sessions() { 427 $this->update_sessions( array() ); 428 } 429 430 /** 431 * Destroy all session tokens for all users. 432 * 433 * @since 4.0.0 434 * @access public 435 * @static 436 */ 437 public static function drop_sessions() { 438 delete_metadata( 'user', 0, 'session_tokens', false, true ); 439 } 440 } 8 require_once( ABSPATH . WPINC . '/class-wp-session-tokens.php' ); 9 require_once( ABSPATH . WPINC . '/class-wp-user-meta-session-tokens.php' );
Note: See TracChangeset
for help on using the changeset viewer.