函数文档

check_password_reset_key()

💡 云策文档标注

概述

check_password_reset_key() 函数用于根据密码重置密钥和用户登录名检索用户行,验证密钥的有效性和过期状态。它返回 WP_User 对象或 WP_Error 对象,并支持过滤钩子以自定义行为。

关键要点

  • 函数接受两个必需参数:$key(密码重置密钥)和 $login(用户登录名),均需为非空字符串。
  • 返回类型为 WP_User 或 WP_Error:成功时返回 WP_User 对象,无效或过期密钥时返回 WP_Error 对象。
  • 密钥过期机制:通过 user_activation_key 字段处理,旧式明文密钥不再接受,但提供不同的 WP_Error 代码以改善用户反馈。
  • 支持过滤钩子:password_reset_expiration 用于自定义密钥过期时间,password_reset_key_expired 用于处理旧式或过期密钥的返回值。
  • 内部使用 wp_verify_fast_hash() 验证密钥哈希,get_user_by() 检索用户信息。

代码示例

function check_password_reset_key(
    #[SensitiveParameter]
    $key,
    $login
) {
    $key = preg_replace( '/[^a-z0-9]/i', '', $key );

    if ( empty( $key ) || ! is_string( $key ) ) {
        return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
    }

    if ( empty( $login ) || ! is_string( $login ) ) {
        return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
    }

    $user = get_user_by( 'login', $login );

    if ( ! $user ) {
        return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
    }

    $expiration_duration = apply_filters( 'password_reset_expiration', DAY_IN_SECONDS );

    if ( str_contains( $user->user_activation_key, ':' ) ) {
        list( $pass_request_time, $pass_key ) = explode( ':', $user->user_activation_key, 2 );
        $expiration_time = $pass_request_time + $expiration_duration;
    } else {
        $pass_key = $user->user_activation_key;
        $expiration_time = false;
    }

    if ( ! $pass_key ) {
        return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
    }

    $hash_is_correct = wp_verify_fast_hash( $key, $pass_key );

    if ( $hash_is_correct && $expiration_time && time() < $expiration_time ) {
        return $user;
    } elseif ( $hash_is_correct && $expiration_time && time() > $expiration_time ) {
        $return = new WP_Error( 'expired_key', __( 'Invalid key.' ) );
        $user_id = $user->ID;
        return apply_filters( 'password_reset_key_expired', $return, $user_id );
    } elseif ( ! $hash_is_correct && wp_check_fast_hash( $user->user_activation_key, $key ) || ( $hash_is_correct && ! $expiration_time ) ) {
        $return = new WP_Error( 'expired_key', __( 'Invalid key.' ) );
        $user_id = $user->ID;
        return apply_filters( 'password_reset_key_expired', $return, $user_id );
    }

    return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
}

注意事项

  • 密钥处理:函数会清理 $key 参数,移除非字母数字字符,确保安全验证。
  • 错误处理:所有无效情况(如空参数、用户不存在、密钥不匹配)均返回 WP_Error 对象,代码为 'invalid_key' 或 'expired_key'。
  • 兼容性:自 3.1.0 版本引入,支持旧式密钥处理,但推荐使用哈希机制以提高安全性。

📄 原文内容

Retrieves a user row based on password reset key and login.

Description

A key is considered ‘expired’ if it exactly matches the value of the user_activation_key field, rather than being matched after going through the hashing process. This field is now hashed; old values are no longer accepted but have a different WP_Error code so good user feedback can be provided.

Parameters

$keystringrequired
The password reset key.
$loginstringrequired
The user login.

Return

WP_User|WP_Error WP_User object on success, WP_Error object for invalid or expired keys.

Source

function check_password_reset_key(
	#[SensitiveParameter]
	$key,
	$login
) {
	$key = preg_replace( '/[^a-z0-9]/i', '', $key );

	if ( empty( $key ) || ! is_string( $key ) ) {
		return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
	}

	if ( empty( $login ) || ! is_string( $login ) ) {
		return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
	}

	$user = get_user_by( 'login', $login );

	if ( ! $user ) {
		return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
	}

	/**
	 * Filters the expiration time of password reset keys.
	 *
	 * @since 4.3.0
	 *
	 * @param int $expiration The expiration time in seconds.
	 */
	$expiration_duration = apply_filters( 'password_reset_expiration', DAY_IN_SECONDS );

	if ( str_contains( $user->user_activation_key, ':' ) ) {
		list( $pass_request_time, $pass_key ) = explode( ':', $user->user_activation_key, 2 );
		$expiration_time                      = $pass_request_time + $expiration_duration;
	} else {
		$pass_key        = $user->user_activation_key;
		$expiration_time = false;
	}

	if ( ! $pass_key ) {
		return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
	}

	$hash_is_correct = wp_verify_fast_hash( $key, $pass_key );

	if ( $hash_is_correct && $expiration_time && time() < $expiration_time ) {
		return $user;
	} elseif ( $hash_is_correct && $expiration_time ) {
		// Key has an expiration time that's passed.
		return new WP_Error( 'expired_key', __( 'Invalid key.' ) );
	}

	if ( hash_equals( $user->user_activation_key, $key ) || ( $hash_is_correct && ! $expiration_time ) ) {
		$return  = new WP_Error( 'expired_key', __( 'Invalid key.' ) );
		$user_id = $user->ID;

		/**
		 * Filters the return value of check_password_reset_key() when an
		 * old-style key or an expired key is used.
		 *
		 * @since 3.7.0 Previously plain-text keys were stored in the database.
		 * @since 4.3.0 Previously key hashes were stored without an expiration time.
		 *
		 * @param WP_Error $return  A WP_Error object denoting an expired key.
		 *                          Return a WP_User object to validate the key.
		 * @param int      $user_id The matched user ID.
		 */
		return apply_filters( 'password_reset_key_expired', $return, $user_id );
	}

	return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
}

Hooks

apply_filters( ‘password_reset_expiration’, int $expiration )

Filters the expiration time of password reset keys.

apply_filters( ‘password_reset_key_expired’, WP_Error $return, int $user_id )

Filters the return value of check_password_reset_key() when an old-style key or an expired key is used.

Changelog

Version Description
3.1.0 Introduced.