Home  >  Article  >  CMS Tutorial  >  Building a Custom WordPress User Flow, Part Three: Password Reset

Building a Custom WordPress User Flow, Part Three: Password Reset

王林
王林Original
2023-09-03 23:05:05837browse

In the first two tutorials of this series, we built custom pages for logging in and registering new users. Now, there’s only one part of the login flow left to explore and replace: What happens if a user forgets their password and wants to reset their WordPress password?

In this tutorial we'll tackle the final step and complete the Personalized Login plugin we've built throughout the series.

The password reset feature in WordPress more or less follows the standard approach on websites today:

  1. The user initiates a reset by entering their username or email address and requesting WordPress to reset their password.
  2. Create a temporary password reset token and store it in user data. A link containing this token will be sent to the user's email address.
  3. The user clicks the link.
  4. On the reset password page, the token is verified and if it matches the user's data, they can choose a new password.

Just like login and new user registration, this functionality is handled through wp-login.php. So the general idea of ​​how we customize this process is now mostly familiar from previous tutorials.

If you haven't read the first two tutorials, it's best to start with Part 1 and work your way through the series in order. You can follow the tutorial and code it yourself, or download the full source code from the linked GitHub repository.

Now, let's start replacing the first screen in the process.

Start WordPress to reset password

Resetting a WP password begins when a user arrives at your login page but cannot remember the password they used on the site.

To do this, we placed a Forgot your password? at the bottom of the Login form in the first part of this series. Message template link. By default, on a WordPress-powered site, this link points to wp-login.php?action=lostpassword, and the page looks like this:

Building a Custom WordPress User Flow, Part Three: Password Reset

To replace this page with a custom page, we will create a function to redirect the user to our custom page and hook the function into a WordPress action.

In this case, we have two options to choose from: we can use the action lost_password, which is called before the page is rendered, or the action we used in the previous tutorial: login_form_{action}, this time it is login_form_lostpassword.

There are two approaches we can take, but in order to limit the amount of unnecessary code executed, let's choose the latter option.

But first, let’s create a new WordPress custom password reset page:

Step 1: Create a reset password page p>

As you remember, in Part 1 we created a function that creates a WordPress page when the plugin is activated using the plugin_activated callback function.

In this function, the definition of the new page is added to the end of the $page_definitions array. In the WordPress password reset process, we also need a second page to select a new password. So to save time we are now also adding a second page.

For clarity, here is the entire array (with the last two page definitions added):

// Information needed for creating the plugin's pages
$page_definitions = array(
    'member-login' => array(
        'title' => __( 'Sign In', 'personalize-login' ),
        'content' => '[custom-login-form]'
    ),
    'member-account' => array(
        'title' => __( 'Your Account', 'personalize-login' ),
        'content' => '[account-info]'
    ),
    'member-register' => array(
        'title' => __( 'Register', 'personalize-login' ),
        'content' => '[custom-register-form]'
    ),
    'member-password-lost' => array(
        'title' => __( 'Forgot Your Password?', 'personalize-login' ),
        'content' => '[custom-password-lost-form]'
    ),
    'member-password-reset' => array(
        'title' => __( 'Pick a New Password', 'personalize-login' ),
        'content' => '[custom-password-reset-form]'
    )
);

The plugin activation callback is only called when the plugin is explicitly activated, so to create these new pages you must deactivate the plugin and then activate it again.

Now, after creating the page, we can redirect the user to member-password-lost instead of wp-login?action=lostpassword.

Step 2: Redirect user to custom page

As I mentioned above, we will use the action login_form_{action} or login_form_lostpassword to cut into .php before wp-login has a chance to render" Lost your password?" Default version. Screen.

In the plugin's constructor, add the following lines:

add_action( 'login_form_lostpassword', array( $this, 'redirect_to_custom_lostpassword' ) );

Then, create the function redirect_to_custom_lostpassword.

This function will check the request method: currently, we only operate on requests sent using the GET method, since these are the requests for displaying the screen. We'll see what happens with POST later.

/**
 * Redirects the user to the custom "Forgot your password?" page instead of
 * wp-login.php?action=lostpassword.
 */
public function redirect_to_custom_lostpassword() {
    if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
        if ( is_user_logged_in() ) {
            $this->redirect_logged_in_user();
            exit;
        }

        wp_redirect( home_url( 'member-password-lost' ) );
        exit;
    }
}

This function is actually the same function we used in the previous tutorial to redirect the user to the custom registration page, just replace the redirect with the page slug of the new page we created above (for some It's a good place to be) Maybe it will be refactored in the future? ).

现在,如果您在登录页面上点击忘记了 WordPress 密码?,您将被重定向到 WordPress 自定义密码重置页面。接下来,让我们创建一个短代码来添加用于启动密码重置的 WordPress 密码表单。

第 3 步:为 WordPress 更改密码表单创建简码

在创建用于启动 WordPress 密码重置的页面时,我们将短代码 [custom-lost-password-form] 添加到其正文中。现在,为了用表单替换短代码,让我们创建一个短代码处理程序。

在插件的构造函数中,添加以下行:

add_shortcode( 'custom-password-lost-form', array( $this, 'render_password_lost_form' ) );

然后,创建用于渲染表单的函数:

/**
 * A shortcode for rendering the form used to initiate the password reset.
 *
 * @param  array   $attributes  Shortcode attributes.
 * @param  string  $content     The text content for shortcode. Not used.
 *
 * @return string  The shortcode output
 */
public function render_password_lost_form( $attributes, $content = null ) {
    // Parse shortcode attributes
    $default_attributes = array( 'show_title' => false );
    $attributes = shortcode_atts( $default_attributes, $attributes );

    if ( is_user_logged_in() ) {
        return __( 'You are already signed in.', 'personalize-login' );
    } else {
        return $this->get_template_html( 'password_lost_form', $attributes );
    }
}

现在,这个函数的大部分内容你已经很熟悉了:首先我们解析短代码参数(show_title 用于决定是否应该在启动密码重置的表单之前呈现标题) 。然后,如果用户未登录,该函数将呈现一个包含 WordPress 忘记密码表单的模板。

现在让我们添加该模板。在 templates 目录中,创建一个新文件,并将其命名为 password_lost_form.php。然后,将以下代码添加到该模板:

<div id="password-lost-form" class="widecolumn">
    <?php if ( $attributes['show_title'] ) : ?>
        <h3><?php _e( 'Forgot Your Password?', 'personalize-login' ); ?></h3>
    <?php endif; ?>

    <p>
        <?php
            _e(
                "Enter your email address and we'll send you a link you can use to pick a new password.",
                'personalize_login'
            );
        ?>
    </p>

    <form id="lostpasswordform" action="<?php echo wp_lostpassword_url(); ?>" method="post">
        <p class="form-row">
            <label for="user_login"><?php _e( 'Email', 'personalize-login' ); ?>
            <input type="text" name="user_login" id="user_login">
        </p>

        <p class="lostpassword-submit">
            <input type="submit" name="submit" class="lostpassword-button"
                   value="<?php _e( 'Reset Password', 'personalize-login' ); ?>"/>
        </p>
    </form>
</div>

如果 show_title 属性设置为 true(第 2-4 行),模板首先显示标题。

接下来是关于第 6-13 行的一些说明和实际表格。正如您在第 15 行中看到的,表单将发布到 WordPress 函数 wp_lostpassword_url 返回的网址,该网址与我们在重定向用户时在上面看到的网址相同到我们的自定义页面。

此表单仅包含一个文本字段,user_login第 18 行)。在此字段中,默认的 WordPress 重置密码功能接受用户的用户名或电子邮件。由于我们使用电子邮件作为用户名,因此它们是相同的,因此我们只要求字段标签中的电子邮件(第 17 行)。

添加此模板后,当您点击登录页面上的忘记密码?消息模板链接时,您将看到如下所示的页面(如果使用 WordPress 默认主题)就像二十十五

Building a Custom WordPress User Flow, Part Three: Password Reset

第 4 步:处理 WordPress 帐户恢复表单提交

现在我们已经创建了 WordPress 密码表单,是时候看看用户提交它时会发生什么了。

为了让我们在不诉诸黑客的情况下进行正确的错误处理,我们需要自己编写一些功能 - 尽可能使用 wp-login.php 中的辅助函数,自然。

为此,我们将在 login_form_lostpassword 操作中添加一个新函数来处理 POST 请求。

该函数将使用 retrieve_password 函数定义在 wp-login.php 中来查找用户并启动密码更新过程。然后,根据是否有错误,该函数将用户重定向到正确的页面:如果出现错误,则返回到忘记密码? 消息模板页面,成功后,进入登录页面。

在构造函数中,添加以下行:

add_action( 'login_form_lostpassword', array( $this, 'do_password_lost' ) );

然后,创建函数:

/**
 * Initiates password reset.
 */
public function do_password_lost() {
    if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
        $errors = retrieve_password();
        if ( is_wp_error( $errors ) ) {
            // Errors found
            $redirect_url = home_url( 'member-password-lost' );
            $redirect_url = add_query_arg( 'errors', join( ',', $errors->get_error_codes() ), $redirect_url );
        } else {
            // Email sent
            $redirect_url = home_url( 'member-login' );
            $redirect_url = add_query_arg( 'checkemail', 'confirm', $redirect_url );
        }

        wp_redirect( $redirect_url );
        exit;
    }
}

该函数首先检查请求方法(在第 5 行上)。由于我们对提交密码丢失表单时的情况感兴趣,因此该函数仅在找到 POST 请求时才会跳转。 GET 请求已由我们之前创建的函数 redirect_to_custom_lostpassword 处理。

然后,在第 6 行,我们调用 WordPress 函数 retrieve_password。该函数的名称有点误导:该函数并不真正检索密码,而是检查表单中的数据,然后通过创建重置 WP 密码令牌并将其通过电子邮件发送给用户,为 WordPress 密码重置准备用户帐户。

如果出现错误(第 7 行),我们会将用户重定向回页面 member-password-lost,并将错误代码作为请求参数传递( 第 8-10 行,实际重定向在第 17 行完成)。

如果一切顺利,用户将被重定向到带有请求参数 checkemail 设置的登录页面(第 12-14 行),以便我们可以向用户。

现在,如果您提交 WordPress 密码表单,一切都应该正常。但为了使用户体验完整,我们需要返回到呈现丢失密码和登录表单的短代码,并显示错误和成功通知。

让我们从积极的方面开始,添加成功消息。

在短代码函数 render_login_form 中,在 get_template_html 调用之前添加以下行:

// Check if the user just requested a new password 
$attributes['lost_password_sent'] = isset( $_REQUEST['checkemail'] ) && $_REQUEST['checkemail'] == 'confirm';

在表单模板中,使用上面的属性添加一条消息:

<?php if ( $attributes['lost_password_sent'] ) : ?>
    <p class="login-info">
        <?php _e( 'Check your email for a link to reset your password.', 'personalize-login' ); ?>
    </p>
<?php endif; ?>

现在,成功启动密码重置后,登录表单应如下所示:

Building a Custom WordPress User Flow, Part Three: Password Reset

要显示错误,我们将返回到丢失的 WordPress 更改密码表单。

首先,在短代码处理程序 render_password_lost_form 中,在渲染模板之前,添加以下行以遍历错误代码并收集数组 中匹配的错误消息$attributes['errors']:

// Retrieve possible errors from request parameters
$attributes['errors'] = array();
if ( isset( $_REQUEST['errors'] ) ) {
    $error_codes = explode( ',', $_REQUEST['errors'] );

    foreach ( $error_codes as $error_code ) {
        $attributes['errors'] []= $this->get_error_message( $error_code );
    }
}

然后,在模板中,我们将呈现错误:

<?php if ( count( $attributes['errors'] ) > 0 ) : ?>
    <?php foreach ( $attributes['errors'] as $error ) : ?>
        <p>
            <?php echo $error; ?>
        </p>
    <?php endforeach; ?>
<?php endif; ?>

最后,将错误消息添加到我们的函数 get_error_messages

// Lost password

case 'empty_username':
    return __( 'You need to enter your email address to continue.', 'personalize-login' );

case 'invalid_email':
case 'invalidcombo':
    return __( 'There are no users registered with this email address.', 'personalize-login' );

接下来,为了完成密码重置流程的第一步,我们来看看如何自定义发送给用户的电子邮件。

第 5 步:自定义 WordPress 更改密码电子邮件

正如我们之前看到的,当发送重置 WP 密码的请求时,在函数 retrieve_password 中,会发送一封 WordPress 更改密码电子邮件,其中包含有关操作的快速说明和一个链接可用于完成密码重置。

消息简短而切题。它完成了它应该做的事情,但您可能想要对其进行自定义以赋予其个人风格,并可能使其更具描述性。

默认文本被硬编码在 wp-login.php 中,但在发送消息之前,WordPress 为插件开发人员提供了使用两个过滤器替换它的机会。

首先,要替换消息正文,您可以使用过滤器 retrieve_password_message。我们现在就开始吧。

在插件的构造函数中,添加以下行:

add_filter( 'retrieve_password_message', array( $this, 'replace_retrieve_password_message' ), 10, 4 );

然后,创建函数 replace_retrieve_password_message

/**
 * Returns the message body for the password reset mail.
 * Called through the retrieve_password_message filter.
 *
 * @param string  $message    Default mail message.
 * @param string  $key        The activation key.
 * @param string  $user_login The username for the user.
 * @param WP_User $user_data  WP_User object.
 *
 * @return string   The mail message to send.
 */
public function replace_retrieve_password_message( $message, $key, $user_login, $user_data ) {
    // Create new message
    $msg  = __( 'Hello!', 'personalize-login' ) . "\r\n\r\n";
    $msg .= sprintf( __( 'You asked us to reset your password for your account using the email address %s.', 'personalize-login' ), $user_login ) . "\r\n\r\n";
    $msg .= __( "If this was a mistake, or you didn't ask for a password reset, just ignore this email and nothing will happen.", 'personalize-login' ) . "\r\n\r\n";
    $msg .= __( 'To reset your password, visit the following address:', 'personalize-login' ) . "\r\n\r\n";
    $msg .= site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . "\r\n\r\n";
    $msg .= __( 'Thanks!', 'personalize-login' ) . "\r\n";

    return $msg;
}

该函数接收四个参数:

  • $message 是发送给用户的消息的默认版本。我们将忽略此参数并从头开始创建我们自己的文本。
  • $key 是用于验证用户密码重置请求的令牌。它需要包含在密码重置链接中。
  • $user_login 是用户的用户名(在我们的例子中是电子邮件地址),密码重置链接中也需要它。
  • $user_data 包含有关用户的一些数据。我们暂时忽略这一点,但如果您愿意,可以在自己的自定义中进一步探索它。

大部分函数只是将消息创建为一系列字符串连接。用于完成密码重置的 URL 是在第 18 行创建的。

为了进行更完整的自定义,一种想法是添加一个设置字段来编辑密码检索消息的内容,并使用它而不是以这种方式在函数内编码消息。

如果您愿意,可以使用过滤器 retrieve_password_title 以同样的方式替换电子邮件标题。过滤器函数采用一个参数,即要发送给用户的默认标题,并且应返回新标题。

进一步自定义的另一种方法是替换整个消息并发送 HTML 消息,例如使用我在之前关于使用 Mandrill 从 WordPress 发送电子邮件的教程中解释的方法。在这种情况下,我将使用 Mandrill API 在上面的过滤器函数中发送消息并返回 false,以便 WordPress 不会再次尝试发送电子邮件。

您现在已经完成了 WordPress 密码重置过程的第一步:用户可以要求重置 WP 密码,该过程由 WordPress 启动。

接下来,我们将了解当用户单击 WordPress 更改密码电子邮件中的链接时会发生什么。

重置 WordPress 密码

正如我们在上面看到的,启动 WordPress 重置密码后,用户将被重定向回登录页面,并附有检查电子邮件的说明。

在 WordPress 更改密码电子邮件中,有一个返回 wp-login.php 的链接,其中参数 loginkey 用于识别用户并验证 WordPress 密码重置请求。当用户单击链接时,WordPress 会验证用户和密钥的有效性,如果一切正常,则让用户设置新密码。

该功能运行良好,我们将使用其中的一部分,调用 wp-login.php 中的现有辅助函数,但同样,由于操作和过滤器在 WordPress 中的组织方式密码重置代码,我们必须重写一些代码才能完成定制。

第 1 步:将用户重定向到您的 WordPress 自定义密码重置页面

首先,我们将首先将用户重定向到我们自己的 WordPress 自定义密码重置页面(我们在本教程开始时创建的页面)。

现在,您可能已经熟悉了:与我们在登录和注册操作以及重置 WP 密码流程中的第一页中所做的相同,我们将使用操作 login_form_{action} 在 WordPress 执行任何操作之前将密码重置操作转移到我们自己的自定义函数。

有两个 wp-login.php 操作用于相同的功能,rpresetpass,所以我们需要将它们重定向到同一函数,redirect_to_custom_password_reset

在插件的构造函数中,添加以下行:

add_action( 'login_form_rp', array( $this, 'redirect_to_custom_password_reset' ) );
add_action( 'login_form_resetpass', array( $this, 'redirect_to_custom_password_reset' ) );

然后,创建函数:

/**
 * Redirects to the custom password reset page, or the login page
 * if there are errors.
 */
public function redirect_to_custom_password_reset() {
    if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
        // Verify key / login combo
        $user = check_password_reset_key( $_REQUEST['key'], $_REQUEST['login'] );
        if ( ! $user || is_wp_error( $user ) ) {
            if ( $user && $user->get_error_code() === 'expired_key' ) {
                wp_redirect( home_url( 'member-login?login=expiredkey' ) );
            } else {
                wp_redirect( home_url( 'member-login?login=invalidkey' ) );
            }
            exit;
        }

        $redirect_url = home_url( 'member-password-reset' );
        $redirect_url = add_query_arg( 'login', esc_attr( $_REQUEST['login'] ), $redirect_url );
        $redirect_url = add_query_arg( 'key', esc_attr( $_REQUEST['key'] ), $redirect_url );

        wp_redirect( $redirect_url );
        exit;
    }
}

该函数首先检查这是一个 GET 请求。 POST 发送到同一 URL 的请求将在下面处理。

然后,在第 8 行,我们调用 WordPress 函数 check_password_reset_key 来验证通过重置 WP 密码链接传递的参数是否有效。如果出现错误,我们会将用户重定向回登录页面,并将错误代码作为请求参数(第 9-16 行)。我们很快就会添加显示错误的代码。

如果参数已成功验证并且允许用户更新其密码,该功能将继续将用户重定向到我们的 WordPress 自定义密码重置页面(仍为空)member-password-reset

在第 19-20 行,我们将参数 keylogin 添加到重定向 URL,以便其他人可以使用它们检查用户何时尝试在下一个屏幕上设置新密码。默认版本的 WordPress 密码重置使用 cookie,但为了教程的目的,我决定使用请求参数以使代码更易于理解。

接下来,让我们创建一个自定义版本的重置 WordPress 密码表单。

第 2 步:显示 WordPress 更改密码表单

点击WordPress更改密码电子邮件链接后向用户显示的重置WordPress密码表单,默认情况下如下所示:

Building a Custom WordPress User Flow, Part Three: Password Reset

这是一个简单的表单,有两个字段,pass1pass2,一个用于输入 WordPress 密码,另一个用于重新输入密码以检查是否有拼写错误。

要创建此表单的自定义版本,我们将使用短代码。

首先,在插件的构造函数中添加以下行:

add_shortcode( 'custom-password-reset-form', array( $this, 'render_password_reset_form' ) );

然后,创建用于渲染表单的函数:

/**
 * A shortcode for rendering the form used to reset a user's password.
 *
 * @param  array   $attributes  Shortcode attributes.
 * @param  string  $content     The text content for shortcode. Not used.
 *
 * @return string  The shortcode output
 */
public function render_password_reset_form( $attributes, $content = null ) {
    // Parse shortcode attributes
    $default_attributes = array( 'show_title' => false );
    $attributes = shortcode_atts( $default_attributes, $attributes );

    if ( is_user_logged_in() ) {
        return __( 'You are already signed in.', 'personalize-login' );
    } else {
        if ( isset( $_REQUEST['login'] ) && isset( $_REQUEST['key'] ) ) {
            $attributes['login'] = $_REQUEST['login'];
            $attributes['key'] = $_REQUEST['key'];

            // Error messages
            $errors = array();
            if ( isset( $_REQUEST['error'] ) ) {
                $error_codes = explode( ',', $_REQUEST['error'] );

                foreach ( $error_codes as $code ) {
                    $errors []= $this->get_error_message( $code );
                }
            }
            $attributes['errors'] = $errors;

            return $this->get_template_html( 'password_reset_form', $attributes );
        } else {
            return __( 'Invalid password reset link.', 'personalize-login' );
        }
    }
}

该函数的核心从第 17 行开始,我们在其中检查用户识别参数登录名和密钥是否存在。如果不是,则密码重置链接无效,我们只会呈现一条错误消息(第 34 行)。

如果检查正常,这两个变量将添加到 $attributes 数组中,以使它们可用于表单模板(第 18-19 行)。

然后,在第 21-30 行,我们已经使用本教程中早期表单中相同的错误传递方法,为提交 WordPress 帐户恢复表单时可能发生的错误做好了准备。 p>

最后,在第 32 行,该函数读取模板并将其返回到 WordPress 进行渲染。

接下来让我们创建模板。在 templates 目录中,创建一个新文件,并将其命名为 password_reset_form.php。添加以下内容:

<div id="password-reset-form" class="widecolumn">
    <?php if ( $attributes['show_title'] ) : ?>
        <h3><?php _e( 'Pick a New Password', 'personalize-login' ); ?></h3>
    <?php endif; ?>

    <form name="resetpassform" id="resetpassform" action="<?php echo site_url( 'wp-login.php?action=resetpass' ); ?>" method="post" autocomplete="off">
        <input type="hidden" id="user_login" name="rp_login" value="<?php echo esc_attr( $attributes['login'] ); ?>" autocomplete="off" />
        <input type="hidden" name="rp_key" value="<?php echo esc_attr( $attributes['key'] ); ?>" />
        
        <?php if ( count( $attributes['errors'] ) > 0 ) : ?>
            <?php foreach ( $attributes['errors'] as $error ) : ?>
                <p>
                    <?php echo $error; ?>
                </p>
            <?php endforeach; ?>
        <?php endif; ?>

        <p>
            <label for="pass1"><?php _e( 'New password', 'personalize-login' ) ?></label>
            <input type="password" name="pass1" id="pass1" class="input" size="20" value="" autocomplete="off" />
        </p>
        <p>
            <label for="pass2"><?php _e( 'Repeat new password', 'personalize-login' ) ?></label>
            <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off" />
        </p>
        
        <p class="description"><?php echo wp_get_password_hint(); ?></p>
        
        <p class="resetpass-submit">
            <input type="submit" name="submit" id="resetpass-button"
                   class="button" value="<?php _e( 'Reset Password', 'personalize-login' ); ?>" />
        </p>
    </form>
</div>

表单以可选标题开头,如果简码属性 show_title 设置为 true(第 2-4 行),则显示该标题。

实际的形式紧跟在标题之后。请注意,该表单将发布到 wp-login.php?action=resetpass第 6 行),与密码重置电子邮件中的链接中使用的 URL 相同,但除外该电子邮件链接使用了简短版本 rp,而不是 resetpass

在表单的开头(第7-8行),我们设置了两个隐藏字段rp_keyrp_login来传递keylogin 参数传递给表单处理程序,该处理程序将使用它们来验证密码更改请求。

在第10-16行,模板将打印出错误(如果有)。此代码与本教程前面的短代码模板中的代码完全相同。

这两个字段在18-25行中打印出来,后面是一些有关选择良好 WordPress 密码的说明以及用于提交 WordPress 更改密码表单的按钮。

WordPress 更改密码表单现在应如下所示:

Building a Custom WordPress User Flow, Part Three: Password Reset

第 3 步:处理 WordPress 重置密码操作

当用户通过单击 WordPress 重置密码按钮提交表单时,其内容将发送到 wp-login.php?action=resetpass,相同的 URL我们在上面使用了将用户重定向到我们的自定义密码重置页面。

当然,当我们自己创建表单时,我们也可以使用不同的 URL。但是,通过保留此默认 URL 并使用 login_form_resetpass (和 login_form_rp,只是为了确定)操作来替换默认功能,我们可以确保没有人意外结束调用默认版本的密码重置。

为此,请再次向构造函数添加两行:

add_action( 'login_form_rp', array( $this, 'do_password_reset' ) );
add_action( 'login_form_resetpass', array( $this, 'do_password_reset' ) );

然后,创建函数:

/**
 * Resets the user's password if the password reset form was submitted.
 */
public function do_password_reset() {
    if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
        $rp_key = $_REQUEST['rp_key'];
        $rp_login = $_REQUEST['rp_login'];

        $user = check_password_reset_key( $rp_key, $rp_login );

        if ( ! $user || is_wp_error( $user ) ) {
            if ( $user && $user->get_error_code() === 'expired_key' ) {
                wp_redirect( home_url( 'member-login?login=expiredkey' ) );
            } else {
                wp_redirect( home_url( 'member-login?login=invalidkey' ) );
            }
            exit;
        }

        if ( isset( $_POST['pass1'] ) ) {
            if ( $_POST['pass1'] != $_POST['pass2'] ) {
                // Passwords don't match
                $redirect_url = home_url( 'member-password-reset' );

                $redirect_url = add_query_arg( 'key', $rp_key, $redirect_url );
                $redirect_url = add_query_arg( 'login', $rp_login, $redirect_url )
                $redirect_url = add_query_arg( 'error', 'password_reset_mismatch', $redirect_url );

                wp_redirect( $redirect_url );
                exit;
            }

            if ( empty( $_POST['pass1'] ) ) {
                // Password is empty
                $redirect_url = home_url( 'member-password-reset' );

                $redirect_url = add_query_arg( 'key', $rp_key, $redirect_url );
                $redirect_url = add_query_arg( 'login', $rp_login, $redirect_url );
                $redirect_url = add_query_arg( 'error', 'password_reset_empty', $redirect_url );

                wp_redirect( $redirect_url );
                exit;
            }

            // Parameter checks OK, reset password
            reset_password( $user, $_POST['pass1'] );
            wp_redirect( home_url( 'member-login?password=changed' ) );
        } else {
            echo "Invalid request.";
        }

        exit;
    }
}

该函数首先检查请求方法,应该是 POST; GET 请求已被上面的重定向函数处理。

然后,它从表单数据中收集密钥和登录参数,并使用它们来验证第 9 行上的密码重置链接,使用 WordPress 函数 check_password_reset_key (我们已经在重定向函数中使用了相同的函数)。

第 10-18 行 中,我们再次检查密码重置密钥检查中可能存在的错误,将用户重定向到忘记密码?消息模板页面进行渲染的错误。

然后,如果重置密钥有效,我们可以专注于 WordPress 帐户恢复表单。

首先,该函数检查两个密码是否匹配(第 21-31 行),然后检查它们是否为空(第 33-43 行)。在这两种情况下,用户都会被重定向回我们的密码重置页面,URL 中包含 keylogin 参数,让用户重试密码更新。 p>

最后,如果所有检查均成功(如果您愿意,可以随意添加更多检查),该函数将使用函数 reset_password 重置 WordPress 密码(位于 第 46 行) )并将用户重定向到登录页面,并将参数 password=changed 附加到 URL 以显示通知。

WordPress 密码现已成功更新,剩下的就是显示成功通知并添加错误消息。

首先,让我们添加通知。在短代码函数 render_login_form 中,添加以下检查:

// Check if user just updated password
$attributes['password_updated'] = isset( $_REQUEST['password'] ) && $_REQUEST['password'] == 'changed';

然后,在渲染表单之前将实际消息添加到模板 login_form.php

<?php if ( $attributes['password_updated'] ) : ?>
    <p class="login-info">
        <?php _e( 'Your password has been changed. You can sign in now.', 'personalize-login' ); ?>
    </p>
<?php endif; ?>

由于我们已经添加了对呈现上述错误消息的支持,剩下的就是将描述性错误消息添加到我们的函数 get_error_message 中。

switch...case 构造中的 default 分支之前添加以下行:

// Reset password

case 'expiredkey':
case 'invalidkey':
    return __( 'The password reset link you used is not valid anymore.', 'personalize-login' );

case 'password_reset_mismatch':
    return __( "The two passwords you entered don't match.", 'personalize-login' );
    
case 'password_reset_empty':
    return __( "Sorry, we don't accept empty passwords.", 'personalize-login' );

结论

就是这样!重置 WP 密码功能已准备就绪,因此我们现在已经完成了 WordPress 登录体验的自定义,从注册新用户到登录并重置丢失的密码。

我希望本系列为您提供了足够的工具,以便您能够更好地进行进一步的自定义(例如,通过向密码重置流程添加新步骤),并更好地了解 wp-login.php 内部发生的情况。

现在,去定制更多内容!

The above is the detailed content of Building a Custom WordPress User Flow, Part Three: Password Reset. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn