web-dev-qa-db-fra.com

Interdire un utilisateur et terminer sa session

Je travaille sur un plugin dérivé de ce tutorial . Jusqu'à présent, le plug-in ajoute une case à cocher sur la page d'édition du profil d'un utilisateur, où les administrateurs peuvent interdire l'utilisateur.

checkbox

Si cette case est cochée, l'utilisateur recevra un message lors de sa connexion:

banned

Ça fonctionne bien. Le problème est que si l'utilisateur est déjà connecté (a une session active) et est banni, l'utilisateur peut continuer à interagir avec le site jusqu'à ce que soit que la session se termine ou que l'utilisateur se déconnecte.

Comment puis-je terminer la session de l'utilisateur lors de l'interdiction afin que l'utilisateur soit expulsé?

Voici le 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 );

Donc, la fin de la session devrait aller dans la fonction rc_ban_user().

EDIT: Plugin complet posté en dessous .

6
Christine Cooper

Utilisez wp_logout(). Il appelle wp_clear_auth_cookie() et invalide immédiatement les informations de connexion actuelles.

Exemple de code, non testé:

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
fuxia

Bien que la méthode de toscho fonctionne, une approche plus simple pourrait consister à utiliser le crochet authenticate pour les empêcher de s'authentifier via un cookie, ou tout autre moyen, de manière plus directe.

Code totalement non testé. Devrait travailler si.

// 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;
}

La chaîne de filtres d'authentification vous permet de décider si un utilisateur est authentifié ou non à toutes les occasions possibles pour s'authentifier. Le renvoi d'une valeur WP_User les connecte. Le renvoi d'un WP_Error de n'importe quel type échoue, mais sa tentative d'authentification a échoué, quelle que soit la méthode employée, que ce soit via nom d'utilisateur/mot de passe ou via cookie.

4
Otto

J'écris aussi un plugin similaire et l'ai déjà publié sur WordPress.org. Je pense que la meilleure solution déposer la session utilisateur immédiatement puis administrateur cliquez sur le bouton "interdire" (bloquer) (lien). Ceci possible avec la classe WP_Session_Tokens:

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

Et même si l'utilisateur est actuellement autorisé et que certaines pages de /wp-admin/ sont ouvertes, elles seront forcées de se déconnecter car nous abandonnons déjà des sessions (immédiatement).

Code source: https://wordpress.org/plugins/mark-user-as-spammer/

2

Le plugin est maintenant prêt à être utilisé et fonctionne avec élégance. Merci à Remi pour le didacticiel original et toscho (le bot) pour la solution opérationnelle à la session de l’utilisateur final après interdiction.

Mises à jour futures

Je prévois ce qui suit pour les futures mises à jour:

  • Option pour supprimer les commentaires et/ou les messages d'un utilisateur lors de l'interdiction.
  • Ajoutez un message d'interdiction personnalisé pour un utilisateur spécifique.
  • Autoriser les administrateurs à interdire plusieurs utilisateurs à la page de liste des utilisateurs dans wp-admin.

Laissez un commentaire si vous avez des suggestions de mise à jour. Je vais éditer cette réponse chaque fois qu'il y a des mises à jour du plugin.

Interdiction des utilisateurs

Créez un dossier nommé ban-users dans votre dossier de plug-in et créez un fichier nommé ban-users.php avec le code suivant:

<?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
Christine Cooper