I’m working on a plugin derived from this tutorial. So far, the plugin adds a checkbox on a user’s profile edit page where admins can ban the user.
If checked, the user will receive a message upon logging in:
It works fine. The problem is, if the user is already logged in (has an active session) and gets banned, the user can continue to interact with the site until either the session ends or the user logs out.
How do I end the user’s session upon banning so the user is forced out?
Here is the code:
/**
* 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 );
So the ending of the session should go in the rc_ban_user()
function.
EDIT: Full plugin posted below.
Use
wp_logout()
. It callswp_clear_auth_cookie()
and invalidates the current log-in information immediately.Sample code, not tested:
While toscho’s method works, a simpler approach might be to use the
authenticate
hook to prevent them from authenticating via cookie, or any other means, in a more direct fashion.Totally untested code. Should work though.
The authenticate filter chain lets you decide whether or not a user is authenticated at every possible opportunity for them to authenticate. Returning a value WP_User logs them in. Returning a WP_Error of any sort fails their authentication attempt, no matter how it was done, whether via username/password or via cookie.
I also write similar plugin and already published it on WordPress.org. I think the best solution drop user session immediately then administrator click “ban” (block) button (link). This possible with
WP_Session_Tokens
class:And even if user currently authorised and some pages from
/wp-admin/
opened they will be force log out because we already drop sessions (immediately).Source code: https://wordpress.org/plugins/mark-user-as-spammer/
The plugin is now ready to be used and functions elegantly. Thanks to Remi for the original tutorial and toscho (the bot) for the working solution to end users session upon banning.
Future Updates
I plan the following for future updates:
Leave a comment if you have any update suggestions. I will edit this answer whenever there are any updates to the plugin.
Ban Users Plugin
Create a folder named
ban-users
in your plugin folder and create a file namedban-users.php
with the following code: