文章參考自:http://www.tutorialstag.com/WordPress-custom-password-reset-page-template.html#codesyntax_2

密碼重置是一個比稍微複雜的過程,因為這個過程需要更多的資料。

在這篇文章之前,我們先了解一下密碼重置的流程:

首先使用者需要重置密碼

  • 一、先訪問本頁面,輸入需要重置密碼賬戶的 Email 或者使用者名稱。
  • 二、系統透過使用者輸入的使用者名稱郵箱給使用者傳送一封郵件,郵件內容中有一個連結地址 (還是本頁面),但是這個連結地址中包含有一個密匙,所以如果訪問本頁面的地址中沒有密匙,則使用者需要輸入使用者名稱或密碼,如果有密匙,那使用者是來重置密碼的而不是提交重置密碼的請求
  • 三、使用者透過郵件中的地址訪問本頁面 (地址中含有密匙),判斷地址中含有密匙,則使用者是來重置密碼的,所以判斷密匙的正確性,如果正確,則透過郵件將生成的新密碼傳送給使用者,如果不正確,則顯示錯誤資訊。

請記住上面說到的兩個 「動作」,重置密碼、提交重置密碼的請求。上面有提到一個密匙,密匙是儲存在資料庫中的,user 表中的 user_activation_key,一般是隨機生成的。

本篇教程呢,以文章模板為例 (使用 url 重寫,請讀者參考前面的文章自行修改),還有由於作者是在自己的電腦上測試,所以並不能百分百確定程式碼可用。

第一步:建立模板檔案

首先在 twenty ten 主題中建立模板檔案:page-passreset.php.

第二步:給模板檔案命名

在檔案開頭新增程式碼

  1. <?php
  2. /*
  3. Template Name: 找回密碼模板
  4. */
  5. ?>

第三步:判斷使用者是否已經登陸

  1. <?php
  2. global $wpdb$user_ID;
  3. wp_enqueue_script( 'jquery' ); //載入 jquery,如果你的主題頭部已經引入,請刪掉
  4. if (!$user_ID) { //判斷使用者是否已經登陸
  5.    //接下來的程式碼應該新增在這裡
  6. else {
  7.     wp_redirect( home_url() ); exit;
  8.     //重定向到首頁
  9. }
  10. ?>

第四步:找回密碼錶單

  1. get_header(); ?>
  2. <script src="http://code.jquery.com/jquery-1.4.4.js"></script><!--載入 js-->
  3. <div id="content" role="main">
  4.     <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
  5.         <form class="user_form" id="wp_pass_reset" action="" method="post">
  6.         <input type="text" class="text" name="user_input" value="" /><br />
  7.         <input type="hidden" name="action" value="tg_pwd_reset" />
  8.         <input type="hidden" name="tg_pwd_nonce" value="<?php echo wp_create_nonce("tg_pwd_nonce"); ?>" />
  9.         <!--wp_create_nonce 函式建立隨機數,用於安全驗證-->
  10.         <input type="submit" id="submitbtn" class="reset_password" name="submit" value="Reset Password" />
  11.         </form>
  12.         <div id="result"></div> <!-- To hold validation results -->
  13.         <script type="text/javascript">
  14.         $("#wp_pass_reset").submit(function() {
  15.             $('#result').html('<span class="loading">Validating...</span>').fadeIn();
  16.             var input_data = $('#wp_pass_reset').serialize();
  17.             $.ajax({
  18.                 type: "POST",
  19.                 url:  "<?php echo get_permalink( $post->ID ); ?>",
  20.                 data: input_data,
  21.                 success: function(msg){
  22.                     $('.loading').remove();
  23.                     $('<div>').html(msg).appendTo('div#result').hide().fadeIn('slow');
  24.                 }
  25.             });
  26.             return false;
  27.         });
  28.         </script>
  29.     <?php endwhileelse : ?>
  30.     <h2><?php _e('沒有找到'); ?></h1>
  31.     <?php endif; ?>
  32. </div><!-- content -->
  33. <?php get_footer();

第五步:「重置」 頁面連結

這裡說的重置,是在需要輸出當前頁面連結地址 (比如重置密碼的郵件中),需要根據當前頁面的 url 形式重置出一個可用的 url 來。你可以將下面的函式新增在頁面頂部 global 變數的後面,也可以放在引入 js 的後面

  1. function tg_validate_url() {
  2.     global $post;
  3.     $page_url = esc_url(get_permalink( $post->ID )); //獲取本頁面的連結地址
  4.     $urlget = strpos($page_url"?");
  5.     if ($urlget === false) {
  6.         $concate = "?";
  7.     } else {
  8.         $concate = "&";
  9.     }
  10.     return $page_url.$concate//返回一個類似 example.com/?     example.com/?p=123&   這樣的 url
  11. }

第六步:請求重置密碼
文章最開始說到,本篇教程中需要區分兩個 「動作」,一個是請求重置程式碼 (輸入郵箱或使用者名稱),其次是重置密碼 (使用者透過郵箱中的連結地址來的),下面的程式碼需要判斷使用者是否提交了資料,所以請注意程式碼中最後面的提示,將第四步中的程式碼包含在那一對大括號中。

  1. if($_POST['action'] == "tg_pwd_reset"){ //判斷是否為請求重置密碼
  2.     if ( !wp_verify_nonce( $_POST['tg_pwd_nonce'], "tg_pwd_nonce")) { //檢查隨機數
  3.         exit("不要開玩笑");
  4.     }
  5.     if(empty($_POST['user_input'])) {
  6.         echo "<div > 請輸入使用者名稱或 E-mail 地址</div>";
  7.         exit();
  8.     }
  9.     //過濾提交的資料
  10.     $user_input = $wpdb->escape(trim($_POST['user_input']));
  11.     if ( strpos($user_input, '@') ) { //判斷使用者提交的是郵件還是使用者名稱
  12.         $user_data = get_user_by_email($user_input); //透過 Email 獲取使用者資料
  13.         if(emptyempty($user_data) || $user_data->caps[administrator] == 1) { //排除管理員
  14.             echo "<div > 無效的 E-mail 地址!</div>";
  15.             exit();
  16.         }
  17.     } else {
  18.         $user_data = get_userdatabylogin($user_input); //透過使用者名稱獲取使用者資料
  19.         if(empty($user_data) || $user_data->caps[administrator] == 1) { //排除管理員
  20.             echo "<div > 無效的使用者名稱!</div>";
  21.             exit();
  22.         }
  23.     }
  24.     $user_login = $user_data->user_login;
  25.     $user_email = $user_data->user_email;
  26.     $key = $wpdb->get_var($wpdb->prepare("SELECT user_activation_key FROM $wpdb->users WHERE user_login = %s"$user_login)); //從資料庫中獲取密匙
  27.     if(empty($key)) { //如果為空
  28.         //generate reset keys 生成 keys
  29.         $key = wp_generate_password(20, false); //生成一個 20 位隨機密碼用做密匙
  30.         $wpdb->update($wpdb->users, array('user_activation_key' => $key), array('user_login' => $user_login)); //更新到資料庫
  31.     }
  32.     //郵件內容
  33.     $message = __('有人提交了重置下面賬戶密碼的請求:') . "

    ";

  34.     $message .= get_option('siteurl') . "

    ";

  35.     $message .= sprintf(__('使用者名稱: %s'), $user_login) . "

    ";

  36.     $message .= __('如果不是您本人操作,請忽略這個郵件即可.') . "

    ";

  37.     $message .= __('如果需要重置密碼,請訪問下面的連結:') . "

    ";

  38.     $message .= tg_validate_url() . "action=reset_pwd&key=$key&login=" . rawurlencode($user_login) . "
    "
    //注意 tg_validate_url(),注意密碼重置的連結地址,需要 actionkeylogin 三個引數
  39.     if ( $message && !wp_mail($user_email, '密碼重置請求', $message) ) {
  40.         echo "<div > 郵件傳送失敗-原因未知。</div>";
  41.         exit();
  42.     } else {
  43.         echo "<div > 我們已經在給你傳送的郵件中說明瞭重置密碼的各項事宜,請注意查收。</div>";
  44.         exit();
  45.     }
  46. else {
  47.     //輸出表單--第四步中的程式碼應該包涵在這個對大括號內
  48. }

第七步:重置密碼

如果使用者是透過重置密碼連結訪問本頁面,那麼 url 中會有 actionkeylogin 三個引數,透過 action 引數來獲取當前動作。

  1. if(isset($_GET['key']) && $_GET['action'] == "reset_pwd") { //如果存在 key 且 action 引數似乎 reset_pwd
  2.     $reset_key = $_GET['key']; //獲取密匙
  3.     $user_login = $_GET['login']; //獲取使用者名稱
  4.     $user_data = $wpdb->get_row($wpdb->prepare("SELECT ID, user_login, user_email FROM $wpdb->users WHERE user_activation_key = %s AND user_login = %s"$reset_key$user_login));
  5.     //透過 key 和使用者名稱驗證資料
  6.     $user_login = $user_data->user_login;
  7.     $user_email = $user_data->user_email;
  8.     if(!empty($reset_key) && !empty($user_data)) {
  9.         $new_password = wp_generate_password(7, false); //生成 7 位隨機密碼
  10.         //echo $new_password; exit();
  11.         wp_set_password( $new_password$user_data->ID ); //重置密碼
  12.         //透過郵件將密碼傳送給使用者
  13.         $message = __('賬戶的新密碼為:') . "

    ";

  14.         $message .= get_option('siteurl') . "

    ";

  15.         $message .= sprintf(__('使用者名稱: %s'), $user_login) . "

    ";

  16.         $message .= sprintf(__('密碼: %s'), $new_password) . "

    ";

  17.         $message .= __('你可以使用你的新密碼透過下面的連結登入: ') . get_option('siteurl')."/login" . "

    ";

  18.         if ( $message && !wp_mail($user_email, '密碼重置請求', $message) ) {
  19.             echo "<div > 郵件傳送失敗-原因未知</div>";
  20.             exit();
  21.         } else {
  22.             $redirect_to = tg_validate_url()."action=reset_success";//跳轉到登陸成功頁面 (還是本頁面地址)
  23.             wp_safe_redirect($redirect_to);
  24.             exit();
  25.         }
  26.     } else{
  27.         exit('無效的 key.');
  28.     }
  29. }

第八步:重置密碼成功
在上一步的程式碼中,重置密碼成功則重定向到一個重置密碼成功的頁面,其實還是本頁面,只不多 action 引數不一樣:

  1. if(isset($_GET['action']) && $_GET['action'] == "reset_success") { //如果動作為 reset_success 就是成功了哇
  2.     exit('<span class="success"> 密碼重置成功,已經透過郵件傳送給您,請查收。</span>');
  3. }

到此,程式碼已經完成。
下面是懶人下載

懶人下載-頁面模板檔案

如果你想透過 url 重寫來實現本頁面,請注意更改相應的 「重置 url 函式」,以及一些涉及到 Url 的地方。