Ticket #37827: 37827.3.diff
File 37827.3.diff, 22.4 KB (added by , 8 years ago) |
---|
-
src/wp-includes/class-wp-session-tokens.php
1 1 <?php 2 2 /** 3 * Session API: WP_Session_Tokens class 4 * 5 * @package WordPress 6 * @subpackage Session 7 * @since 4.7.0 8 */ 9 10 /** 3 11 * Abstract class for managing user session tokens. 4 12 * 5 13 * @since 4.0.0 … … 307 315 */ 308 316 public static function drop_sessions() {} 309 317 } 310 311 /**312 * Meta-based user sessions token manager.313 *314 * @since 4.0.0315 */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.0322 * @access protected323 *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.0355 * @access protected356 *357 * @param string $verifier Verifier of the session to retrieve.358 * @return array|null The session, or null if it does not exist359 */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.0374 * @access protected375 *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.0395 * @access protected396 *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.0411 * @access protected412 *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.0424 * @access protected425 */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.0434 * @access public435 * @static436 */437 public static function drop_sessions() {438 delete_metadata( 'user', 0, 'session_tokens', false, true );439 }440 } -
src/wp-includes/class-wp-user-meta-session-tokens.php
1 1 <?php 2 2 /** 3 * Abstract class for managing user session tokens.3 * Session API: WP_User_Meta_Session_Tokens class 4 4 * 5 * @since 4.0.0 5 * @package WordPress 6 * @subpackage Session 7 * @since 4.7.0 6 8 */ 7 abstract class WP_Session_Tokens {8 9 9 /**10 * User ID.11 *12 * @since 4.0.013 * @access protected14 * @var int User ID.15 */16 protected $user_id;17 18 /**19 * Protected constructor.20 *21 * @since 4.0.022 *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 out33 * the session manager for a subclass of WP_Session_Tokens.34 *35 * @since 4.0.036 * @access public37 * @static38 *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.046 *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.058 * @access private59 *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.076 * @access public77 *78 * @param string $token Session token79 * @return array User session80 */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.092 * @access public93 *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 cookie106 * link that cookie to an expiration time and to ensure the cookie107 * becomes invalidated upon logout.108 *109 * This function generates a token and stores it with the associated110 * expiration time (and potentially other session information via the111 * {@see 'attach_session_information'} filter).112 *113 * @since 4.0.0114 * @access public115 *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 as124 * IP address or user agent to a session.125 *126 * @since 4.0.0127 *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 // Timestamp145 $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.0158 * @access public159 *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.0172 * @access public173 *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.0186 * @access public187 *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.0205 * @access protected206 *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.0218 * @access public219 */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.0228 * @access public229 * @static230 */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.0240 * @access public241 *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.0252 * @access protected253 *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.0262 * @access protected263 *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.0275 * @access protected276 *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.0287 * @access protected288 *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.0297 * @access protected298 */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.0305 * @access public306 * @static307 */308 public static function drop_sessions() {}309 }310 311 10 /** 312 11 * Meta-based user sessions token manager. 313 12 * -
src/wp-includes/session.php
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' ); 10 No newline at end of file