問題描述

我正在從一個從這個 tutorial 派生的外掛。到目前為止,該外掛在使用者的個人資料編輯頁面上新增了一個核取方塊,管理員可以禁止使用者。

如果選中,使用者將在登入時收到訊息:

工作正常問題是,如果使用者已經登入 (有活動會話) 並被禁止,使用者可以繼續與站點進行互動,直到會話結束或使用者登出。

禁止使用者結束使用者會話,使使用者被強制退出?

這是程式碼:

/**
 * Admin init
 *
 * @access      public
 * @since       1.0
 * @return      void
*/
function rc_admin_init(){

    // Edit user profile
    add_action( 'edit_user_profile', 'rc_edit_user_profile' );
    add_action( 'edit_user_profile_update', 'rc_edit_user_profile_update' );

}
add_action('admin_init', 'rc_admin_init' );


/**
 * Adds custom checkbox to user edition page
 *
 * @access      public
 * @since       1.0
 * @return      void
*/
function rc_edit_user_profile() {
    if ( !current_user_can( 'edit_users' ) ) {
        return;
    }

    global $user_id;

    // User cannot disable itself
    $current_user = wp_get_current_user();
    $current_user_id = $current_user->ID;
    if ( $current_user_id == $user_id ) {
        return;
    }
    ?>
    <h3>Ban user</h3>
    <table class="form-table">
    <tr>
        <th scope="row"></th>
        <td><label for="rc_ban"><input name="rc_ban" type="checkbox" id="rc_ban"  /> Check to ban user.</label></td>
    </tr>
    </table>
    <?php
}


/**
 * Save custom checkbox
 *
 * @access      public
 * @since       1.0
 * @return      void
*/
function rc_edit_user_profile_update() {

    if ( !current_user_can( 'edit_users' ) ) {
        return;
    }

    global $user_id;

    // User cannot disable itself
    $current_user    = wp_get_current_user();
    $current_user_id = $current_user->ID;
    if ( $current_user_id == $user_id ) {
        return;
    }

    // Lock
    if( isset( $_POST['rc_ban'] ) && $_POST['rc_ban'] = 'on' ) {
        rc_ban_user( $user_id );
    } else { // Unlock
        rc_unban_user( $user_id );
    }

}


/**
 * Ban user
 *
 * @access      public
 * @since       1.0
 * @return      void
*/
function rc_ban_user( $user_id ) {

    $old_status = rc_is_user_banned( $user_id );

    // Update status
    if ( !$old_status ) {
        update_user_option( $user_id, 'rc_banned', true, false );
    }
}


/**
 * Un-ban user
 *
 * @access      public
 * @since       1.0
 * @return      void
*/
function rc_unban_user( $user_id ) {

    $old_status = rc_is_user_banned( $user_id );

    // Update status
    if ( $old_status ) {
        update_user_option( $user_id, 'rc_banned', false, false );
    }
}


/**
 * Checks if a user is already banned
 *
 * @access      public
 * @since       1.0
 * @return      void
*/
function rc_is_user_banned( $user_id ) {
    return get_user_option( 'rc_banned', $user_id, false );
}


/**
 * Check if user is locked while login process
 *
 * @access      public
 * @since       1.0
 * @return      void
*/
function rc_authenticate_user( $user ) {

    if ( is_wp_error( $user ) ) {
        return $user;
    }

    // Return error if user account is banned
    $banned = get_user_option( 'rc_banned', $user->ID, false );
    if ( $banned ) {
        return new WP_Error( 'rc_banned', __('<strong>ERROR</strong>: This user account is disabled.', 'rc') );
    }

    return $user;
}

add_filter( 'wp_authenticate_user', 'rc_authenticate_user', 1 );

所以會話的結束應該在 rc_ban_user()函式中。

編輯:全外掛釋出 below

最佳解決方案

使用 wp_logout()。它呼叫 wp_clear_auth_cookie()並立即使當前的 log-in 資訊無效。

示例程式碼,未測試:

add_action( 'init', 'log_out_banned_user' );

function log_out_banned_user() {
    if ( ! is_user_logged_in() )
        return;

    $user = wp_get_current_user();

    if ( ! get_user_option( 'rc_banned', $user->ID, false ) )
        return;

    wp_logout();
    wp_redirect( home_url( '/' ) );
    exit;
}

次佳解決方案

雖然 toscho 的方法有效,但更簡單的方法可能是使用 authenticate 鉤子來防止他們以更直接的方式透過 cookie 或任何其他方式進行身份驗證。

完全未經測試的程式碼。應該工作雖然

// the priority of 999 is to ensure it's last in the auth chain
add_filter('authenticate', 'force_fail_banned_users', 999, 3);

function force_fail_banned_users($user, $username, $password) {
    if ( ! is_a($user, 'WP_User') ) {
        // we only care about actual users who already auth'd okay via some means
        return $user;
    }

    if ( rc_is_user_banned( $user->ID ) ) {
        // user is banned, so return a failure case
        return new WP_Error('banned_user', 'Banned message goes here.');
    }

    // user not banned, so return the user normally
    return $user;
}

驗證過濾器鏈可讓您決定使用者是否在每個可能的機會進行身份驗證。返回值 WP_User 會記錄它們。返回任何型別的 WP_Error,無論是透過使用者名稱/密碼還是透過 cookie,都無法透過身份驗證嘗試。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。