web-dev-qa-db-fra.com

Rediriger l'utilisateur à l'aide du crochet d'action 'wp_login_failed' si l'erreur est 'empty_username' ou 'empty_password'

Contexte

J'essaie de créer une connexion frontale sans faille pour un blog, tout en laissant wp-login.php disponible pour les utilisateurs qui savent comment s'y rendre. wp-login.php est également requis pour authentifier les identifiants de session, il ne peut donc pas être supprimé complètement.

J'y suis presque, mais j'ai un problème avec les échecs de connexion, plus précisément avec un nom d'utilisateur vide.

Question

Quelqu'un sait-il qu'il est possible d'arrêter l'affichage de wp-login.php pour les erreurs de nom d'utilisateur/mot de passe vides, tout en évitant qu'une erreur ne soit affichée pour la même raison lorsqu'un utilisateur accède directement à wp-login.php?

Mon travail

J'ai localisé le crochet wp_login_failed et créé la fonction ci-dessous. Fondamentalement, il ajoute des arguments de requête pour indiquer que la connexion a échoué et quel nom d'utilisateur a été entré avant de rediriger l'utilisateur vers la connexion frontale. Avec les arguments de la requête, je peux alors déterminer pourquoi la connexion a échoué et afficher un message à l'utilisateur.

add_action('wp_login_failed', 'djg_front_end_login_fail');
function djg_front_end_login_fail($username){

    $referrer = (isset($_SERVER['HTTP_REFERER'])) ? $_SERVER['HTTP_REFERER'] : $_SERVER['PHP_SELF'];
    $referrer = add_query_arg('result', 'failed', $referrer);
    $referrer = add_query_arg('username', $username, $referrer);

    if(!empty($referrer) && !strstr($referrer, 'wp-login') && !strstr($referrer, 'wp-admin')) :
        wp_redirect($referrer);
        exit;
    endif;

}

Cependant, j'ai remarqué que si le champ du nom d'utilisateur était vide, je n'étais pas redirigé, mais l'utilisateur était toujours affiché wp-login.php.

Après une inspection plus poussée, j'ai trouvé la fonction wp_authenticate(), où j'ai remarqué que si la première erreur de connexion était empty_username ou empty_password, le hook d'action wp_login_failed n'était pas ajouté. Pour contrer cela, j'ai utilisé le crochet de filtre authenticate et en fait, j'ai ajouté le code des erreurs susmentionnées, en leur faisant précéder djg_, afin qu'elles ne soient pas ignorées.

add_filter('authenticate', 'djg_authenticate_login', 99, 3);
function djg_authenticate_login($user, $username, $password){;

    if(is_wp_error($user)) :

        $codes = $user->get_error_codes();
        $messages = $user->get_error_messages();

        $user = new WP_Error;

        for($i = 0; $i <= count($codes) - 1; $i++) :

            $code = $codes[$i];
            if(in_array($code, array('empty_username', 'empty_password'))) :
                $code = 'djg_' . $code;
            endif;

            $user->add($code, $messages[$i]);

        endfor;

    endif;

    return $user;

}

Cela fonctionne, mais maintenant si les utilisateurs accèdent directement à la page wp-login.php, qui doit rester disponible (comme décrit dans Background ), une erreur est affichée -

ERREUR: le champ Nom d'utilisateur est vide.
ERREUR: Le champ du mot de passe est vide.

Enfin, après avoir tiré beaucoup de cheveux, j'ai trouvé dans la fonction wp_signon() le code qui le provoquait, mais à mon sens, je ne vois aucun filtre qui me permette de modifier le comportement n'importe où autour de l'extrait. En gros, cela signifie que si les erreurs sont exactement empty_username et empty_password, ignorez-les. -

if ( is_wp_error($user) ) {
    if ( $user->get_error_codes() == array('empty_username', 'empty_password') ) {
        $user = new WP_Error('', '');
    }

    return $user;
}

Détails

  • wp_authenticate() se trouve dans /wp-includes/pluggable.php
  • Le crochet de filtre authenticate se trouve dans la fonction wp_authenticate()
  • Le hook d'action wp_login_failed se trouve dans la fonction wp_authenticate()
  • wp_signon() se trouve dans /wp-includes/user.php

Question (encore)

Quelqu'un sait-il qu'il est possible d'arrêter l'affichage de wp-login.php pour les erreurs de nom d'utilisateur vides, tout en évitant qu'une erreur ne soit affichée pour la même raison lorsqu'un utilisateur accède directement à wp-login.php?

6
David Gard

WordPress gère la connexion a échoué de deux manières:

  1. S'il s'agit d'une mauvaise information d'identification et que le nom d'utilisateur et le mot de passe ont une valeur, cette action peut être capturée par wp_login_failed
  2. Si les deux options, ou une seule, sont vides, WordPress génère l'objet d'erreur en tant que premier paramètre du filtre d'authentification. il ne s'ouvre pas et l'action wp_login_failed capture cette cause/cet événement

Pour ce que nous avons fait ici, voir les commentaires dans le code:

add_filter( 'authenticate', function( $user, $username, $password ) {
    // forcefully capture login failed to forcefully open wp_login_failed action, 
    // so that this event can be captured
    if ( empty( $username ) || empty( $password ) ) {
        do_action( 'wp_login_failed', $user );
    }
    return $user;
}, 10, 3 );

// to handle even you can handle the error like
add_action( 'wp_login_failed', function( $username ) {
    if ( is_wp_error( $username ) ) {
        // perform operation on error object for empty error
    }
} );
7
palash140