¿Cómo puedo redirigir al usuario después de ingresar una contraseña incorrecta?
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' )
) );

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

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

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.

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

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.

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

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

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/

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.

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

Lo siguiente funcionó para mí. Ambos hooks se pueden encontrar dentro de la función wp_authenticate
en wp-includes/pluggable.php
.
- 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);
- 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);

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

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

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>

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