Забанить пользователя и завершить его сеанс
Я работаю над плагином, полученным из этого учебника . До сих пор плагин добавляет флажок на странице редактирования профиля пользователя, где администраторы могут запретить пользователю.
Если флажок установлен, пользователь получит сообщение при входе в систему:
Это прекрасно работает. Проблема в том, что если пользователь уже вошел в систему (имеет активный сеанс) и забанен, пользователь может продолжать взаимодействовать с сайтом до либо сеанса завершается или пользователь выходит из системы.
Как мне завершить сеанс пользователя после запрета, чтобы пользователь был удален?
Вот код:
/**
* 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()
.
РЕДАКТИРОВАТЬ: Полный плагин опубликован ниже.
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;
}
Хотя метод тошо работает, более простым подходом может быть использование крючка 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.
Я также пишу аналогичный плагин и уже опубликовал его на 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/
Теперь плагин готов к использованию и работает элегантно. Спасибо Реми за оригинальный учебник и тошо (боту) за рабочее решение для сеанса конечных пользователей после запрета.
Будущие обновления
Я планирую следующее для будущих обновлений:
- Возможность удалять комментарии или/и сообщения пользователя после запрета.
- Добавьте пользовательское сообщение о запрете для определенного пользователя.
- Разрешить администраторам блокировать нескольких пользователей в списке пользователей страница в 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 );