¿Cómo puedo redirigir al usuario después de ingresar una contraseña incorrecta?

26 abr 2011, 17:07:13
Vistas: 65.1K
Votos: 23

Estoy usando wp_login_form() para mostrar el formulario de inicio de sesión en una ventana de diálogo jQuery.

Si el usuario ingresa una contraseña incorrecta, es llevado al backend. No quiero eso. ¿Hay alguna manera de notificar al usuario que ingresó una contraseña incorrecta y que permanezca en la misma página?

Antes de que existiera wp_login_form() estaba usando un plugin. Espero poder evitar usar un plugin para esto.

Mi código:

wp_login_form( array(
  'label_remember' => __( 'Recordarme' ),
  'label_log_in' => __( 'Iniciar Sesión' )
) );
0
Todas las respuestas a la pregunta 9
4
34

Llegué aquí desde Google. Pero la respuesta no me satisfizo. Estuve buscando un rato y encontré una mejor solución.

Añade esto a tu archivo functions.php:

add_action( 'wp_login_failed', 'my_front_end_login_fail' );  // Hook para login fallido

function my_front_end_login_fail( $username ) {
   $referrer = $_SERVER['HTTP_REFERER'];  // ¿De dónde vino el intento de login?
   // Si hay un referrer válido y no es la pantalla de login por defecto
   if ( !empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin') ) {
      wp_redirect( $referrer . '?login=failed' );  // Añadimos información (login=failed) a la URL para que el tema pueda usarlo
      exit;
   }
}
9 jun 2012 00:06:53
Comentarios

Gracias Alexey, voy a probar esto (ya que todavía estoy usando un plugin)

Steven Steven
20 jun 2012 02:29:54

La solución de Alexey funciona cuando se ingresan credenciales incorrectas, pero desafortunadamente falla cuando el usuario olvida ingresar el nombre de usuario o contraseña. Aparentemente Wordpress ni siquiera intenta iniciar sesión en este caso, por lo que la acción wp_login_failed no se ejecuta.

Szczepan Hołyszewski Szczepan Hołyszewski
12 sept 2012 10:39:23

Yo usaría wp_get_referer() aquí para ahorrar tiempo: http://codex.wordpress.org/Function_Reference/wp_get_referer

Jake Jake
3 jul 2013 20:00:49

Además, definitivamente debes usar add_query_arg aquí, por lo que el wp_redirect debería ser: "wp_redirect( add_query_arg('login', 'failed', $referrer) );"

Jake Jake
3 jul 2013 20:14:24
4
25

El método actual que estoy usando para manejar todos los problemas mencionados aquí funciona muy bien incluso con nombre de usuario/contraseña en blanco y no depende de javascript (aunque el js podría funcionar bien junto con esto).

add_action( 'wp_login_failed', 'custom_login_failed' );
function custom_login_failed( $username )
{
    $referrer = wp_get_referer();

    if ( $referrer && ! strstr($referrer, 'wp-login') && ! strstr($referrer,'wp-admin') )
    {
        wp_redirect( add_query_arg('login', 'failed', $referrer) );
        exit;
    }
}

La clave es este filtro para cambiar cómo se trata un nombre de usuario/contraseña en blanco:

add_filter( 'authenticate', 'custom_authenticate_username_password', 30, 3);
function custom_authenticate_username_password( $user, $username, $password )
{
    if ( is_a($user, 'WP_User') ) { return $user; }

    if ( empty($username) || empty($password) )
    {
        $error = new WP_Error();
        $user  = new WP_Error('authentication_failed', __('<strong>ERROR</strong>: Nombre de usuario inválido o contraseña incorrecta.'));

        return $error;
    }
}

Puedes llevar esto un paso más allá y reemplazar completamente wp-login.php redirigiendo a los usuarios a tu página de inicio de sesión personalizada y usar esa página también para la redirección de login_failed. Código completo:

/**
 * Acciones de la Página de Inicio de Sesión Personalizada
 */
// Cambia la URL de inicio de sesión en todo el sitio a la página de inicio de sesión personalizada
add_filter( 'login_url', 'custom_login_url', 10, 2 );
// Redirige wp-login a inicio de sesión personalizado con algunas variables de consulta de error personalizadas cuando sea necesario
add_action( 'login_head', 'custom_redirect_login', 10, 2 );
// Actualiza el fallo de inicio de sesión para enviar al usuario de vuelta al formulario personalizado con una variable de consulta
add_action( 'wp_login_failed', 'custom_login_failed', 10, 2 );
// Actualiza la autenticación para devolver un error cuando un campo o ambos están en blanco
add_filter( 'authenticate', 'custom_authenticate_username_password', 30, 3);
// Agrega automáticamente el formulario de inicio de sesión a la página "login"
add_filter( 'the_content', 'custom_login_form_to_login_page' );

/**
 * Funciones de la Página de Inicio de Sesión Personalizada
 */
function custom_login_url( $login_url='', $redirect='' )
{
    $page = get_page_by_path('login');
    if ( $page )
    {
        $login_url = get_permalink($page->ID);

        if (! empty($redirect) )
            $login_url = add_query_arg('redirect_to', urlencode($redirect), $login_url);
    }
    return $login_url;
}
function custom_redirect_login( $redirect_to='', $request='' )
{
    if ( 'wp-login.php' == $GLOBALS['pagenow'] )
    {
        $redirect_url = custom_login_url();

        if (! empty($_GET['action']) )
        {
            if ( 'lostpassword' == $_GET['action'] )
            {
                return;
            }
            elseif ( 'register' == $_GET['action'] )
            {
                $register_page = get_page_by_path('register');
                $redirect_url = get_permalink($register_page->ID);
            }
        }
        elseif (! empty($_GET['loggedout'])  )
        {
            $redirect_url = add_query_arg('action', 'loggedout', custom_login_url());
        }

        wp_redirect( $redirect_url );
        exit;
    }
}
function custom_login_failed( $username )
{
    $referrer = wp_get_referer();

    if ( $referrer && ! strstr($referrer, 'wp-login') && ! strstr($referrer, 'wp-admin') )
    {
        if ( empty($_GET['loggedout']) )
        wp_redirect( add_query_arg('action', 'failed', custom_login_url()) );
        else
        wp_redirect( add_query_arg('action', 'loggedout', custom_login_url()) );
        exit;
    }
}
function custom_authenticate_username_password( $user, $username, $password )
{
    if ( is_a($user, 'WP_User') ) { return $user; }

    if ( empty($username) || empty($password) )
    {
        $error = new WP_Error();
        $user  = new WP_Error('authentication_failed', __('<strong>ERROR</strong>: Nombre de usuario inválido o contraseña incorrecta.'));

        return $error;
    }
}
function custom_login_form_to_login_page( $content )
{
    if ( is_page('login') && in_the_loop() )
    {
        $output = $message = "";
        if (! empty($_GET['action']) )
        {
            if ( 'failed' == $_GET['action'] )
                $message = "Hubo un problema con tu nombre de usuario o contraseña.";
            elseif ( 'loggedout' == $_GET['action'] )
                $message = "Ahora has cerrado sesión.";
            elseif ( 'recovered' == $_GET['action'] )
                $message = "Revisa tu correo electrónico para el enlace de confirmación.";
        }

        if ( $message ) $output .= '<div class="message"><p>'. $message .'</p></div>';
        $output .= wp_login_form('echo=0&redirect='. site_url());
        $output .= '<a href="'. wp_lostpassword_url( add_query_arg('action', 'recovered', get_permalink()) ) .'" title="Recuperar Contraseña Perdida">¿Contraseña perdida?</a>';

        $content .= $output;
    }
    return $content;
}

Personaliza y agrega estos para añadir tu logo a la página wp-login para recuperación de contraseña:

// llamándolo solo en la página de inicio de sesión
add_action( 'login_enqueue_scripts', 'custom_login_css', 10 );
function custom_login_css() { wp_enqueue_style( 'custom_login_css', get_template_directory_uri() .'/library/css/login.css', false ); }
// cambiando el enlace del logo de wordpress.org a tu sitio
add_filter( 'login_headerurl', 'custom_login_logo_url' );
function custom_login_logo_url() { return home_url(); }
// cambiando el texto alternativo en el logo para mostrar el nombre de tu sitio
add_filter( 'login_headertitle', 'custom_login_title' );
function custom_login_title() { return get_option('blogname'); }

CSS para el logo de inicio de sesión:

.login h1 a {
    background: url(../images/login-logo.png) no-repeat top center;
    width: 274px;
    height: 63px;
    text-indent: -9999px;
    overflow: hidden;
    padding-bottom: 15px;
    display: block;
}

EDITO: Acabo de implementar esto en otro sitio desde cero, y encontré que el "paso adicional" anterior es más completo, y corregí pequeños errores de sintaxis en los "add_actions". Agregué algunos comentarios y un método para agregar automáticamente el formulario de inicio de sesión a la página de login sin un archivo de plantilla separado. El método del formulario de inicio de sesión debería funcionar en la mayoría de los casos, ya que está adjunto a "the_content", podría causar un problema si tienes más de un loop en la página de login, solo usa una plantilla page-login.php en ese caso.

3 jul 2013 21:11:07
Comentarios

Gracias, voy a revisar esto (y ver si puedo hacer que funcione junto con inicio de sesión de terceros como Twitter y Facebook)

Steven Steven
4 jul 2013 00:15:12

Jake - esta es una solución completa y buena. Gracias por compartir. +1

henrywright henrywright
30 sept 2013 00:39:16

Esto básicamente está integrado en un plugin llamado Sewn In Template Login, un plugin bastante completo y pequeño. https://wordpress.org/plugins/sewn-in-template-log-in/

Jake Jake
31 ene 2016 00:05:34

Bien, el único problema es que en realidad no muestra los errores en el front-end....

Siyah Siyah
9 may 2019 11:43:49
0

wp_login_form() crea un formulario con un atributo action de site_url/wp-login.php, lo que significa que cuando haces clic en el botón de enviar, el formulario se envía a site_url/wp-login.php que ignora redirect_to en errores (como contraseña incorrecta). Por lo tanto, en tu caso, puedes volver a usar un plugin o recrear todo el proceso de inicio de sesión para tener control sobre los errores. Echa un vistazo a Verificar nombre de usuario correcto en formulario de inicio de sesión personalizado que es una pregunta muy similar.

26 abr 2011 18:53:25
0

Una solución para el punto de Szczepan Hołyszewski sobre campos vacíos en la solución aceptada, el siguiente código jQuery evitará ir a la página estándar de wp-login: (agregar a la plantilla de página de inicio de sesión o footer.php)

jQuery("#loginform-custom").submit(function(){
     var isFormValid = true;
       jQuery("input").each(function()
       {
       if (jQuery.trim($(this).val()).length == 0){
       jQuery(this).addClass("submit_error");
       isFormValid = false;
       }     
     else {
     jQuery(this).removeClass("submit_error");
     }
     });
     return isFormValid;
});
9 may 2013 23:57:17
0

Lo siguiente funcionó para mí. Ambos hooks se pueden encontrar dentro de la función wp_authenticate en wp-includes/pluggable.php.

  1. Verificar mediante el filtro authenticate si el formulario de inicio de sesión carece de nombre de usuario o contraseña.
function wpse_15633_redirectMissingDataLoginForm($user, $username, $password)
{
    $errors = [];
    empty(trim($password)) && $errors[] = 'password_empty';
    empty(trim($username)) && $errors[] = 'username_empty';

    if (! empty($errors)) {

        $redirect_url = add_query_arg([
            'errors' => join(',', $errors),
        ], site_url('login', 'login_post'));

        if (wp_safe_redirect($redirect_url)) {
            exit;
        }
    }
    return $user;
}
add_filter('authenticate', 'wpse_15633_redirectMissingDataLoginForm', 10, 3);
  1. Verificar mediante la acción wp_login_failed si la autenticación del nombre de usuario y contraseña proporcionados ha fallado.
function wpse_15633_redirectFailedLoginForm($username, $error)
{
    $redirect_url = add_query_arg([
        'errors' => $error->get_error_code(),
    ], site_url('login', 'login_post'));

    if (wp_safe_redirect($redirect_url)) {
        exit;
    }
}
add_action('wp_login_failed', 'wpse_15633_redirectFailedLoginForm', 10, 2);
30 ago 2020 17:12:08
2

Una adición a la respuesta de Alexey. Puedes agregar una función de jQuery para verificar que uno de los campos no esté vacío. De esta manera, el formulario no se enviará a menos que haya algo que verificar, evitando que WordPress redirija a /wp-login.php.

  <script>
        $("#wp-submit").click(function() {
          var user = $("input#user_login").val();
            if (user == "") {
            $("input#user_login").focus();
            return false;
          }
         });
  </script>   

Todavía no estoy seguro de cómo solucionar el aspecto del olvido de contraseña

26 feb 2013 07:09:33
Comentarios

Tenga en cuenta que WordPress carga jQuery en modo "Sin Conflicto". El alias $ no funciona.

s_ha_dum s_ha_dum
26 feb 2013 07:38:10

También debes considerar que el usuario presiona [enter] y no hace clic en el botón de inicio de sesión. Además, necesitas verificar también si la contraseña está en blanco.

Steven Steven
26 feb 2013 13:07:41
0

Añadiendo a la útil respuesta de @alexey y aportando algo para manejar el problema que otros han mencionado.

Su código para colocar en el archivo functions.php:

add_action( 'wp_login_failed', 'my_front_end_login_fail' );  // hook para login fallido

function my_front_end_login_fail( $username ) {
   $referrer = $_SERVER['HTTP_REFERER'];  // ¿de dónde vino el envío del formulario?
   // si hay un referer válido y no es la pantalla de inicio de sesión por defecto
   if ( !empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin') ) {
      wp_redirect( $referrer . '?login=failed' );  // agreguemos información (login=failed) a la URL para que el tema la use
      exit;
   }
}

Sin embargo, como otros han señalado, si los campos están vacíos, WordPress no valida y los usuarios terminan en la pantalla de inicio de sesión del backend.

Para solucionar esto, añado un script justo después de crear el formulario que agrega required a los inputs para que el navegador detenga cualquier envío si los campos están vacíos.

En la página donde está tu formulario:

<?php 
$args = array(
    'form_id' => 'YOUR-FORM-NAME',
); 
wp_login_form( $args );
?>
<script>
if(jQuery('form#YOUR-FORM-NAME').length) { 
    jQuery('form#YOUR-FORM-NAME input').each(function() {
        jQuery(this).attr("required", true);
    });
}
</script>
3 may 2023 19:28:20
0

Yo solo quería que en caso de fallo de inicio de sesión (o campo vacío), el usuario permaneciera en la misma página, con el mensaje de error. Probé el código anterior pero hay varios errores... ¿encontraste una forma más fácil de hacerlo? Gracias.

31 ene 2025 15:00:33
1
-1
jQuery("#loginform-custom").submit(function(){
     var isFormValid = true;
       jQuery("input").each(function()
       {
       if (jQuery.trim($(this).val()).length == 0){
       jQuery(this).addClass("submit_error");
       isFormValid = false;
       }     
     else {
     jQuery(this).removeClass("submit_error");
     }
     });
     return isFormValid;
});
11 may 2018 15:20:30
Comentarios

Por favor [edita] tu respuesta, y añade una explicación: ¿por qué podría eso resolver el problema?

fuxia fuxia
11 may 2018 16:06:17