Enviando el enlace de restablecimiento de contraseña programáticamente

31 jul 2012, 14:48:54
Vistas: 74.4K
Votos: 43

Tengo esta página creada manualmente:

$user_login = sanitize_text_field( $_GET['user_login'] );

if ( username_exists( $user_login ) ||  email_exists($user_login) ) { ?>
<!--Todo ha sido validado, continuar ....-->

<!DOCTYPE HTML>
<html lang="es-ES">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript">
        function submit()
        {
            var f = document.getElementById('lostpasswordform');
            f.onclick = function () { };
            document.lostpasswordform.submit();
        }
    </script>
</head>
<body onload="submit()">

    <form name="lostpasswordform" id="lostpasswordform" action="<?php echo esc_url( site_url( 'wp-login.php?action=lostpassword', 'login_post' ) ); ?>" method="post">

        <input type="hidden" name="user_login" id="user_login" class="input" value="<?php echo ($user_login); ?>" />

    <?php do_action('lost_password'); ?>

    </form>

</body>
</html>

<?php
    echoXITO";
    exit();
} else {
    echo "¡El nombre de usuario o email introducido es incorrecto, por favor inténtelo de nuevo!";
}

Todo parece correcto, pero no funciona cuando se llama desde una aplicación. Si visito manualmente domain.example/forgot-password?user_login=username sí envía correctamente el email de restablecimiento de contraseña.

3
Comentarios

por app te refieres a plugin

Amit Kosti Amit Kosti
1 ago 2012 15:19:14

no, app - android

Nimbuz Nimbuz
1 ago 2012 15:51:42

no funciona ¿qué ocurre?

pcarvalho pcarvalho
3 ago 2012 11:06:52
Todas las respuestas a la pregunta 9
1
28

Así que si deseas enviar el enlace para restablecer la contraseña y tienes acceso al código base, puedes usar el siguiente fragmento y modificarlo según necesites. De hecho, este código es una versión ligeramente modificada de wp-login.php

/**
 * Maneja el envío del correo electrónico para recuperar la contraseña al usuario.
 *
 * @uses $wpdb Objeto de la base de datos de WordPress
 * @param string $user_login Nombre de usuario o correo electrónico
 * @return bool true en caso de éxito, false en caso de error
 */
function retrieve_password($user_login) {
    global $wpdb, $current_site;

    if ( empty( $user_login) ) {
        return false;
    } else if ( strpos( $user_login, '@' ) ) {
        $user_data = get_user_by( 'email', trim( $user_login ) );
        if ( empty( $user_data ) )
           return false;
    } else {
        $login = trim($user_login);
        $user_data = get_user_by('login', $login);
    }

    do_action('lostpassword_post');


    if ( !$user_data ) return false;

    // redefinir user_login asegura que devolvemos el caso correcto en el correo
    $user_login = $user_data->user_login;
    $user_email = $user_data->user_email;

    do_action('retreive_password', $user_login);  // Error ortográfico y obsoleto
    do_action('retrieve_password', $user_login);

    $allow = apply_filters('allow_password_reset', true, $user_data->ID);

    if ( ! $allow )
        return false;
    else if ( is_wp_error($allow) )
        return false;

    $key = $wpdb->get_var($wpdb->prepare("SELECT user_activation_key FROM $wpdb->users WHERE user_login = %s", $user_login));
    if ( empty($key) ) {
        // Generar algo aleatorio para la clave...
        $key = wp_generate_password(20, false);
        do_action('retrieve_password_key', $user_login, $key);
        // Ahora insertar la nueva clave md5 en la base de datos
        $wpdb->update($wpdb->users, array('user_activation_key' => $key), array('user_login' => $user_login));
    }
    $message = __('Alguien ha solicitado que se restablezca la contraseña para la siguiente cuenta:') . "\r\n\r\n";
    $message .= network_home_url( '/' ) . "\r\n\r\n";
    $message .= sprintf(__('Nombre de usuario: %s'), $user_login) . "\r\n\r\n";
    $message .= __('Si esto fue un error, simplemente ignora este correo y no pasará nada.') . "\r\n\r\n";
    $message .= __('Para restablecer tu contraseña, visita la siguiente dirección:') . "\r\n\r\n";
    $message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user_login), 'login') . ">\r\n";

    if ( is_multisite() )
        $blogname = $GLOBALS['current_site']->site_name;
    else
        // La opción blogname se escapa con esc_html al ingresar a la base de datos en sanitize_option
        // queremos revertir esto para el texto plano de los correos.
        $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);

    $title = sprintf( __('[%s] Restablecimiento de contraseña'), $blogname );

    $title = apply_filters('retrieve_password_title', $title);
    $message = apply_filters('retrieve_password_message', $message, $key);

    if ( $message && !wp_mail($user_email, $title, $message) )
        wp_die( __('El correo electrónico no pudo ser enviado.') . "<br />\n" . __('Posible razón: tu servidor puede tener deshabilitada la función mail()...') );

    return true;
}

$user_login = sanitize_text_field( $_GET['user_login'] );

if (retrieve_password($user_login)) {
    echo "ÉXITO";
} else {
    echo "ERROR";
}
3 ago 2012 14:09:00
Comentarios

Esto no está funcionando correctamente para mí. Lo he introducido en un plugin personalizado y lo he puesto en mi sitio, pero está causando un problema donde cuando instalo el plugin y luego hago clic en 'Cerrar sesión', no me desconecta del sitio. ¿Alguna idea de por qué ocurre esto?

MxmastaMills MxmastaMills
11 oct 2013 11:04:07
2
21

La respuesta anterior no funcionó para mí (dice que el código es inválido en la página de inicio de sesión de WP), probablemente porque la respuesta tiene 1,5 años y algo ha cambiado en el código de WP, así que he actualizado un poco este código (también desde wp-login.php), aquí está:

function retrieve_password($user_login){
    global $wpdb, $wp_hasher;

    $user_login = sanitize_text_field($user_login);
    
    if ( empty( $user_login) ) {
        return false;
    } else if ( strpos( $user_login, '@' ) ) {
        $user_data = get_user_by( 'email', trim( $user_login ) );
        if ( empty( $user_data ) )
           return false;
    } else {
        $login = trim($user_login);
        $user_data = get_user_by('login', $login);
    }

    do_action('lostpassword_post');


    if ( !$user_data ) return false;

    // redefinir user_login asegura que devolvamos el caso correcto en el email
    $user_login = $user_data->user_login;
    $user_email = $user_data->user_email;

    do_action('retreive_password', $user_login);  // Error ortográfico y obsoleto
    do_action('retrieve_password', $user_login);

    $allow = apply_filters('allow_password_reset', true, $user_data->ID);

    if ( ! $allow )
        return false;
    else if ( is_wp_error($allow) )
        return false;
        
    $key = wp_generate_password( 20, false );
    do_action( 'retrieve_password_key', $user_login, $key );

    if ( empty( $wp_hasher ) ) {
        require_once ABSPATH . 'wp-includes/class-phpass.php';
        $wp_hasher = new PasswordHash( 8, true );
    }
    $hashed = time() . ':' . $wp_hasher->HashPassword( $key );
    $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user_login ) );

    $message = __('Alguien solicitó que se restableciera la contraseña para la siguiente cuenta:') . "\r\n\r\n";
    $message .= network_home_url( '/' ) . "\r\n\r\n";
    $message .= sprintf(__('Nombre de usuario: %s'), $user_login) . "\r\n\r\n";
    $message .= __('Si esto fue un error, ignora este correo electrónico y no pasará nada.') . "\r\n\r\n";
    $message .= __('Para restablecer tu contraseña, visita la siguiente dirección:') . "\r\n\r\n";
    $message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user_login), 'login') . ">\r\n";

    if ( is_multisite() )
        $blogname = $GLOBALS['current_site']->site_name;
    else
        $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);

    $title = sprintf( __('[%s] Restablecimiento de contraseña'), $blogname );

    $title = apply_filters('retrieve_password_title', $title);
    $message = apply_filters('retrieve_password_message', $message, $key);

    if ( $message && !wp_mail($user_email, $title, $message) )
        wp_die( __('El correo electrónico no pudo ser enviado.') . "<br />\n" . __('Posible razón: tu host puede haber deshabilitado la función mail()...') );

    echo '<p>El enlace para restablecer la contraseña ha sido enviado a tu correo electrónico. Por favor revisa tu email.</p>';;
}
10 mar 2014 21:09:20
Comentarios

Esto funcionó para mí. La respuesta aceptada para la versión 3.8.1 no funcionó y resultó en una clave expirada. Específicamente, en el procesamiento de $key y la actualización de user_activation_key.

Rolice Rolice
27 mar 2014 23:27:32

Esta respuesta también resultó en un enlace expirado para mí y no funcionó.

Dan Hennion Dan Hennion
5 ene 2017 18:57:49
0
12

Ninguna de las respuestas anteriores funcionó para mí, así que revisé wp-login.php para ver su funcionalidad predeterminada de restablecimiento. Utilizaron la función get_password_reset_key( $userData ). En caso de que alguien se quede estancado con las respuestas anteriores, aquí está mi solución:

            $userData = get_userdata($user_id);             

            $user_login = $userData->user_login;
            $user_email = $userData->user_email;
            $key = get_password_reset_key( $userData );


            $message = __('Alguien ha solicitado restablecer la contraseña para la siguiente cuenta:') . "\r\n\r\n";
            $message .= network_home_url( '/' ) . "\r\n\r\n";
            $message .= sprintf(__('Nombre de usuario: %s'), $user_login) . "\r\n\r\n";
            $message .= __('Si fue un error, simplemente ignora este correo y no pasará nada.') . "\r\n\r\n";
            $message .= __('Para restablecer tu contraseña, visita la siguiente dirección:') . "\r\n\r\n";
            $message .= network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user_login), 'login');
31 jul 2017 09:07:44
0

Noté que después de actualizar WordPress a la versión 4.3, lo anterior ya no funcionaba para mi plugin personalizado. Siempre indicaba que la clave no era válida.

Cambiar:

$hashed = $wp_hasher->HashPassword( $key );

por

$hashed = time() . ':' . $wp_hasher->HashPassword( $key );

Esto solucionó el problema para mí, espero que ayude a alguien más

31 ago 2015 02:56:33
0

WordPress 4.3.1

function retrieve_password($user_login){
    global $wpdb, $wp_hasher;
    $user_login = sanitize_text_field($user_login); // Sanitiza el campo de entrada
    if ( empty( $user_login) ) {
        return false; // Retorna falso si el campo está vacío
    } else if ( strpos( $user_login, '@' ) ) {
        $user_data = get_user_by( 'email', trim( $user_login ) ); // Busca usuario por email
        if ( empty( $user_data ) )
           return false; // Retorna falso si no encuentra el usuario
    } else {
        $login = trim($user_login);
        $user_data = get_user_by('login', $login); // Busca usuario por nombre de usuario
    }

    do_action('lostpassword_post'); // Acción hook para después de enviar formulario de contraseña perdida
    if ( !$user_data ) return false; // Verifica si existe el usuario
    // Redefinir user_login asegura que devolvemos el caso correcto en el email
    $user_login = $user_data->user_login;
    $user_email = $user_data->user_email;
    do_action('retreive_password', $user_login);  // Hook mal escrito y obsoleto
    do_action('retrieve_password', $user_login);  // Hook correcto
    $allow = apply_filters('allow_password_reset', true, $user_data->ID);
    if ( ! $allow )
        return false; // Filtro para permitir/denegar el reseteo
    else if ( is_wp_error($allow) )
        return false;
    $key = wp_generate_password( 20, false ); // Genera clave de reseteo
    do_action( 'retrieve_password_key', $user_login, $key );

    if ( empty( $wp_hasher ) ) {
        require_once ABSPATH . 'wp-includes/class-phpass.php';
        $wp_hasher = new PasswordHash( 8, true ); // Crea hash de contraseña
    }
    $hashed = $wp_hasher->HashPassword( $key );    
    $wpdb->update( $wpdb->users, array( 'user_activation_key' => time().":".$hashed ), array( 'user_login' => $user_login ) ); // Actualiza clave en BD
    $message = __('Alguien ha solicitado restablecer la contraseña de la siguiente cuenta:') . "\r\n\r\n"; // Mensaje del email
    $message .= network_home_url( '/' ) . "\r\n\r\n";
    $message .= sprintf(__('Nombre de usuario: %s'), $user_login) . "\r\n\r\n";
    $message .= __('Si fue un error, ignora este correo y no pasará nada.') . "\r\n\r\n";
    $message .= __('Para restablecer tu contraseña, visita la siguiente dirección:') . "\r\n\r\n";
    $message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user_login), 'login') . ">\r\n";

    if ( is_multisite() )
        $blogname = $GLOBALS['current_site']->site_name; // Nombre del sitio en multisitio
    else
        $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES); // Nombre del blog

    $title = sprintf( __('[%s] Restablecimiento de contraseña'), $blogname );

    $title = apply_filters('retrieve_password_title', $title); // Filtro para título
    $message = apply_filters('retrieve_password_message', $message, $key); // Filtro para mensaje

    if ( $message && !wp_mail($user_email, $title, $message) )
        wp_die( __('El correo no pudo ser enviado.') . "<br />\n" . __('Posible razón: tu servidor puede tener deshabilitada la función mail()...') );

    echo '<p>Se ha enviado un enlace para restablecer tu contraseña a tu correo electrónico. Por favor revisa tu bandeja de entrada.</p>';;
}
8 dic 2015 12:22:56
1

Ejemplo Combinado (Probado en 5.2)

Formulario Frontend

<form id="form-password-reset" action="<?php echo wp_lostpassword_url(); ?>" method="post">
  <?php wp_nonce_field( 'ajax-resetpassword-nonce', 'security' ); ?>
  <div class="text-align-center margin-bottom-32">
     <h3 class="h3">Restablecer tu contraseña</h3>
  </div>
  <div class="row">
     <div class="col-12 col-md-4">
        <div class="form-group">
           <label for="auth-password-reset-email">Correo electrónico</label>
           <div class="form-input-wrapper">
              <input type="email" class="form-input" id="auth-password-reset-email" name="email" placeholder="ej. nombre@dominio.com">
           </div>
        </div>
        <button type="submit" class="btn-solid btn-primary btn-block">
        Enviar</button>
        <p class="form__error margin-top-16">
           // TODO puedes mostrar el mensaje aquí
        </p>
     </div>
     <div class="col-12 col-md-4"></div>
  </div>
</form>

JS para manejar el envío AJAX

$(form).on('submit', function (event) {
  event.preventDefault(event)
  const email = $(`#auth-password-reset-email`).val()
  const security = $(`#security`).val()
  const action = 'authResetPassword'
  var has_error = false;

  if (email.length <= 0) {
   // TODO
    has_error = true;
  }

  if (security.length <= 0) {
    // TODO
    has_error = true;
  }

  if (has_error == true) {
    // TODO
    return false
  }

  $.ajax({
    type: 'POST',
    dataType: 'json',
    url: ajax.ajaxurl,
    data: {  action, email, security },
    success: function (data) {
      if (data.status) {
         // TODO
      }
      if (!data.status) {
          // TODO
      }
    }
  })

  return false;
})

Lado del servidor para generar el enlace de restablecimiento y enviar el correo

try {
    check_ajax_referer('ajax-resetpassword-nonce', 'security');
    $response = [
        "status" => false,
        "error" => true,
        "data" => "",
    ];

    extract($_POST);

    $user_email = sanitize_text_field($email);

    $user = get_user_by( 'email', $user_email );
    if( $user instanceof WP_User ) {
        $user_id = $user->ID;
        $user_info = get_userdata($user_id);
        $unique = get_password_reset_key( $user_info );
        $unique_url = network_site_url("wp-login.php?action=rp&key=$unique&login=" . rawurlencode($user_info->user_login), 'login');

        $subject  = "Enlace para restablecer contraseña";
        $message = __('Alguien ha solicitado restablecer la contraseña para la siguiente cuenta:') . "\r\n\r\n";
        $message  = "<p>Hola ".ucfirst( $user_info->first_name ).",</p>";
        $message .= network_home_url( '/' ) . "\r\n\r\n";
        $message .= sprintf(__('Usuario: %s'), $user_info->user_login) . "\r\n\r\n";
        $message .= __('Si fue un error, ignora este correo y no pasará nada.') . "\r\n\r\n";
        $message .= __('Para restablecer tu contraseña, visita la siguiente dirección:') . "\r\n\r\n";
        $message .=  $unique_url;

        wp_mail( $user_email, $subject, $message ); // TODO
        $response['data'] = [ "message" =>  __('Enlace para restablecer contraseña enviado.'), 'reset_link' => $unique_url ];
        wp_send_json($response);
    }

    $response['data'] = [ "message" =>  __('El correo electrónico no existe.') ];
    wp_send_json($response);

} catch (Exception $e) {
    wp_send_json([
        "status" => false,
        "error" => false,
        "data" => ["message" => $e->getMessage() ]
    ]);
}

Para mostrar tu propio formulario personalizado de restablecimiento de contraseña

add_action( 'login_form_lostpassword', 'redirect_to_custom_lostpassword' );
function redirect_to_custom_lostpassword() {
  if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
      if ( is_user_logged_in() ) {
         // TODO
          exit;
      }

      wp_redirect( home_url( 'restablecer-contrasena-personalizado' ) ); // TODO
      exit;
  }
}
3 ene 2021 09:01:49
Comentarios

¿Y el formulario para crear una nueva contraseña después del restablecimiento?)

aprinciple aprinciple
4 jun 2022 19:50:45
0

Como la solución anterior no funcionó para mí, hice algunos cambios menores en el código de Bhavesh Vala.

Reemplaza:

$key = wp_generate_password( 20, false );

Con esto:

$key = get_password_reset_key( $user_data );

Y no necesitas usar la consulta de actualización, así que elimina la siguiente consulta:

$wpdb->update( $wpdb->users, array( 'user_activation_key' => time().":".$hashed ), array( 'user_login' => $user_login ) );

¡Feliz programación!

20 feb 2020 08:51:52
0

No pude hacer que ninguna de estas soluciones funcionara elegantemente en WordPress (probando en WP 6.2.2), pero después de revisar el repositorio de WP en Github, resulta que es sorprendentemente simple en la solicitud AJAX para restablecer una contraseña.

/* Asumiendo que ya tienes la variable $user_login configurada */

$results = retrieve_password( $user_login ); // Dispara el correo de restablecimiento de contraseña
if($results === true) {
    // Éxito
} else {
    // Error
}

Si solo tienes el ID de usuario, puedes recuperar el inicio de sesión usando el siguiente código:

/* Asumiendo que ya tienes la variable $user_id configurada */

$user = get_userdata( $user_id);
$results = retrieve_password( $user->user_login ); // Dispara el correo de restablecimiento de contraseña
3 jul 2023 17:46:59
0

Prueba esto

$wpdb->update( $wpdb->users, array( 'user_activation_key' => $key ), array( 'user_login' => $user_login ) );

en lugar de

$wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user_login ) );

Me funcionó (WordPress 4.3.1)

23 oct 2015 09:05:49