Забанить пользователя и завершить его сеанс


Я работаю над плагином, полученным из этого учебника . До сих пор плагин добавляет флажок на странице редактирования профиля пользователя, где администраторы могут запретить пользователю.

checkbox

Если флажок установлен, пользователь получит сообщение при входе в систему:

banned

Это прекрасно работает. Проблема в том, что если пользователь уже вошел в систему (имеет активный сеанс) и забанен, пользователь может продолжать взаимодействовать с сайтом до либо сеанса завершается или пользователь выходит из системы.

Как мне завершить сеанс пользователя после запрета, чтобы пользователь был удален?

Вот код:

/**
 * 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().

РЕДАКТИРОВАТЬ: Полный плагин опубликован ниже.

Author: Community, 2013-11-20

4 answers

Используйте wp_logout(). Он вызывает wp_clear_auth_cookie() и немедленно аннулирует текущую информацию о входе в систему.

Пример кода, не проверенный:

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;
}
 5
Author: fuxia, 2013-11-20 20:18:57

Хотя метод тошо работает, более простым подходом может быть использование крючка 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.

 4
Author: Otto, 2013-11-20 22:37:40

Я также пишу аналогичный плагин и уже опубликовал его на WordPress.org . Я думаю, что лучшим решением будет немедленно удалить сеанс пользователя, а затем администратор нажмет кнопку "запретить" (заблокировать) (ссылка). Это возможно с классом WP_Session_Tokens:

$manager = \WP_Session_Tokens::get_instance( $user_id );
$manager->destroy_all();

И даже если пользователь в настоящее время авторизован и некоторые страницы из /wp-admin/ открыты, они будут принудительно выведены из системы, потому что мы уже удаляем сеансы (немедленно).

Исходный код: https://wordpress.org/plugins/mark-user-as-spammer/

 2
Author: Kolya Korobochkin, 2017-03-13 10:20:58

Теперь плагин готов к использованию и работает элегантно. Спасибо Реми за оригинальный учебник и тошо (боту) за рабочее решение для сеанса конечных пользователей после запрета.

Будущие обновления

Я планирую следующее для будущих обновлений:

  • Возможность удалять комментарии или/и сообщения пользователя после запрета.
  • Добавьте пользовательское сообщение о запрете для определенного пользователя.
  • Разрешить администраторам блокировать нескольких пользователей в списке пользователей страница в wp-admin.

Оставьте комментарий, если у вас есть какие-либо предложения по обновлению. Я буду редактировать этот ответ всякий раз, когда будут какие-либо обновления плагина.

Плагин для запрета пользователей

Создайте папку с именем ban-users в папке вашего плагина и создайте файл с именем ban-users.php со следующим кодом:

<?php
/*
Plugin Name: Ban Users
Plugin URI: http://wordpress.stackexchange.com/questions/123902/ban-a-user-and-end-their-session
Description: Allows you to ban users
Author: Christine Cooper, Remi, toscho
Version: 1.1
Author URI: http://wordpress.stackexchange.com/questions/123902/ban-a-user-and-end-their-session
*/


/**
 * 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" <?php if ( get_user_option( 'rc_banned', $user_id, false ) ) { echo 'checked'; } ?> /> 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 );
}



/**
 * End a users active session if they are banned
 * By toscho http://wordpress.stackexchange.com/a/123903/24875
 *
 * @access      public
 * @since       1.1 
 * @return      void
*/
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;
}



/**
 * 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>: Your user account has been disabled.', 'rc') );
    }

    return $user;
}

add_filter( 'wp_authenticate_user', 'rc_authenticate_user', 1 );
 1
Author: Christine Cooper, 2013-11-29 15:08:11