php

Autenticar usuario con base de datos de WordPress

En este post te mostraré cómo autenticar un usuario existente de WordPress desde un lugar externo; es decir, desde otro sistema, software, código o como le quieras llamar.

Dicho con otras palabras, te mostraré cómo hacer un login externo usando el usuario y contraseña de los usuarios de WordPress.

Por ejemplo, yo tengo un sistema en el que quiero autenticar a los usuarios con los que ya tengo en mi WordPress, así que quiero reutilizar esa tabla de usuarios y verificar si la contraseña y usuario coinciden, sin usar las funciones de WordPress.

Requisitos para leer base de datos de WordPress

Autenticar usuario de WordPress con PHP

Esto lo vamos a hacer con PHP, pero técnicamente hablando se podría hacer desde cualquier lenguaje de programación que pueda conectarse a MySQL y usar el algoritmo de hasheo de WP.

Para que funcione con PHP, el programa debe estar en el mismo servidor que el sitio de WordPress, y si no, al menos la base de datos debe estar disponible de manera remota.

Comprobar contraseña de WordPress

Esto es como hacer un login simple, lo que va a cambiar será el modo de comprobar si la contraseña es correcta, pues vamos a usar PasswordHash: Portable PHP password hashing framework.

Puedes descargarlo desde la página oficial, e incluirlo como mejor lo prefieras.

Obteniendo base de datos

En este caso usaré PDO para obtener una conexión a la base de datos. Recuerda cambiar las credenciales como sea necesario.

<?php
function obtenerBaseDeDatosWordPress()
{
    $pass = "";
    $usuario = "root";
    $nombreBaseDeDatos = "wp";
    $baseDeDatos = new PDO('mysql:host=localhost;dbname=' . $nombreBaseDeDatos, $usuario, $pass);
    $baseDeDatos->query("set names utf8;");
    $baseDeDatos->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
    $baseDeDatos->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $baseDeDatos->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
    return $baseDeDatos;
}

Como puedes ver es una simple conexión a la base de datos de MySQL de WordPress en donde están almacenados los usuarios.

Obtener usuario de WordPress

Ahora que tenemos la conexión, vamos a leer los datos. Los usuarios están en wp_users (me parece que puede cambiar si cambiaste el prefijo de las tablas, así que podría ser simplemente users) y sus roles (administrador, suscriptor, colaborador) están en wp_usermeta por lo que la consulta y la función quedan así:

<?php
function obtenerUsuarioDeWordPress($usuarioOCorreo)
{
    $bd = obtenerBaseDeDatosWordPress();
    $sentencia = $bd->prepare("SELECT * FROM wp_users 
INNER JOIN wp_usermeta ON wp_users.ID = wp_usermeta.user_id 
WHERE (wp_users.user_login = ? OR wp_users.user_email = ?) AND wp_usermeta.meta_key = ?");
    $sentencia->execute([$usuarioOCorreo, $usuarioOCorreo, "wp_capabilities"]);
    return $sentencia->fetchObject();
}

En este caso el usuario puede autenticarse con el correo o con el nombre de usuario. La función regresará un objeto de usuario que tendrá todos los datos del mismo.

Aquí hay algo muy importante y es que el rol está dentro de meta_value pero este valor está serializado así que debemos usar unserialize y hacer un montón de comprobaciones para saber el rol.

Autenticar usuario

Ahora que ya tenemos esa función, veamos cómo autenticar. Lo que hacemos es:

  • Obtener el usuario de la base de datos de WordPress
  • Incluir a PasswordHash para comprobar la contraseña
  • Si todo es correcto, volvemos a regresar al usuario, con el rol ya arreglado
  • Si algo falla (la contraseña no es correcta, no existe el usuario, etcétera) regresamos false

Entonces queda así:

<?php
function autenticarUsuario($username, $password)
{
    # Obtener usuario. Si no existe, regresamos false inmediatamente
    $usuario = obtenerUsuarioDeWordPress($username);
    if (!$usuario) return false;
    # Incluimos PasswordHash pues vamos a realizar algunas comprobaciones
    include_once "PasswordHash.php";
    # Esta es la contraseña almacenada en la base de datos:
    $storedHash = $usuario->user_pass;
    # Crear instancia de PasswordHash
    $passwordHash = new PasswordHash(8, false);
    $metaValue = unserialize($usuario->meta_value);
    # Nota: en mi caso solo permito usuarios administradores y colaboradores; ignoro a los demás.
    # Si tú quieres permitirlos, modifica el código
    if (!isset($metaValue["administrator"]) && !isset($metaValue["contributor"])) {
        return false;
    }
    if ((isset($metaValue["administrator"]) && !$metaValue["administrator"]) && (isset($metaValue["contributor"]) && !$metaValue["contributor"])) {
        return false;
    }
    # Ahora sí comprobamos la contraseña plana ($password) con la hasheada almacenada ($storedHash)
    if ($passwordHash->CheckPassword($password, $storedHash)) {
        # Si llegamos aquí, el usuario y contraseña son correctos
        # Lo único que hacemos es poner el rol del mismo
        if ((isset($metaValue["administrator"])) && $metaValue["administrator"]) {
            $usuario->role = "administrator";
        } else if (isset($metaValue["contributor"]) && $metaValue["contributor"]) {
            $usuario->role = "contributor";
        }
        # Y regresamos el usuario
        return $usuario;
    } else {
        # Caso contrario (la contraseña no coincide) regresamos igualmente false
        return false;
    }
}

La función recibe el nombre de usuario o correo, y la contraseña plana. Obtiene el usuario, comprueba los datos y en caso de que todo vaya bien, regresará el usuario.

Si la contraseña no coincide o el usuario no existe, regresa false. A partir de la llamada de esta función podríamos iniciar sesión, pues si nos regresa un usuario podemos iniciar y establecer datos en la sesión.

A continuación te mostraré un ejemplo de uso de la función.

Poniendo todo junto

También he grabado un vídeo explicando el código, te invito a verlo y a que te suscribas:

Veamos el ejemplo completo, a continuación el código. Recuerda que la clase PasswordHash.php debe estar en el mismo directorio que este código.

<?php
/*
  ____          _____               _ _           _       
 |  _ \        |  __ \             (_) |         | |      
 | |_) |_   _  | |__) |_ _ _ __ _____| |__  _   _| |_ ___ 
 |  _ <| | | | |  ___/ _` | '__|_  / | '_ \| | | | __/ _ \
 | |_) | |_| | | |  | (_| | |   / /| | |_) | |_| | ||  __/
 |____/ \__, | |_|   \__,_|_|  /___|_|_.__/ \__, |\__\___|
         __/ |                               __/ |        
        |___/                               |___/         
    
____________________________________
/ Si necesitas ayuda, contáctame en \
\ https://parzibyte.me               /
 ------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Creado por Parzibyte (https://parzibyte.me). Este encabezado debe mantenerse intacto,
excepto si este es un proyecto de un estudiante.
*/function obtenerBaseDeDatosWordPress()
{
    $pass = "";
    $usuario = "root";
    $nombreBaseDeDatos = "wp";
    $baseDeDatos = new PDO('mysql:host=localhost;dbname=' . $nombreBaseDeDatos, $usuario, $pass);
    $baseDeDatos->query("set names utf8;");
    $baseDeDatos->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
    $baseDeDatos->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $baseDeDatos->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
    return $baseDeDatos;
}


function obtenerUsuarioDeWordPress($usuarioOCorreo)
{
    $bd = obtenerBaseDeDatosWordPress();
    $sentencia = $bd->prepare("SELECT * FROM wp_users 
INNER JOIN wp_usermeta ON wp_users.ID = wp_usermeta.user_id 
WHERE (wp_users.user_login = ? OR wp_users.user_email = ?) AND wp_usermeta.meta_key = ?");
    $sentencia->execute([$usuarioOCorreo, $usuarioOCorreo, "wp_capabilities"]);
    return $sentencia->fetchObject();
}

function autenticarUsuario($username, $password)
{
    # Obtener usuario. Si no existe, regresamos false inmediatamente
    $usuario = obtenerUsuarioDeWordPress($username);
    if (!$usuario) return false;
    # Incluimos PasswordHash pues vamos a realizar algunas comprobaciones
    include_once "PasswordHash.php";
    # Esta es la contraseña almacenada en la base de datos:
    $storedHash = $usuario->user_pass;
    # Crear instancia de PasswordHash
    $passwordHash = new PasswordHash(8, false);
    $metaValue = unserialize($usuario->meta_value);
    # Nota: en mi caso solo permito usuarios administradores y colaboradores; ignoro a los demás.
    # Si tú quieres permitirlos, modifica el código
    if (!isset($metaValue["administrator"]) && !isset($metaValue["contributor"])) {
        return false;
    }
    if ((isset($metaValue["administrator"]) && !$metaValue["administrator"]) && (isset($metaValue["contributor"]) && !$metaValue["contributor"])) {
        return false;
    }
    # Ahora sí comprobamos la contraseña plana ($password) con la hasheada almacenada ($storedHash)
    if ($passwordHash->CheckPassword($password, $storedHash)) {
        # Si llegamos aquí, el usuario y contraseña son correctos
        # Lo único que hacemos es poner el rol del mismo
        if ((isset($metaValue["administrator"])) && $metaValue["administrator"]) {
            $usuario->role = "administrator";
        } else if (isset($metaValue["contributor"]) && $metaValue["contributor"]) {
            $usuario->role = "contributor";
        }
        # Y regresamos el usuario
        return $usuario;
    } else {
        # Caso contrario (la contraseña no coincide) regresamos igualmente false
        return false;
    }
}

# Momento de probar. Usaré <pre> para que se vea de mejor manera, pero recuerda que solo estoy depurando ;)
echo "<pre>";
echo "Debería mostrar los datos correctos: ";
$usuarioCorrecto = autenticarUsuario("parzibyte", "hunter2");
echo json_encode($usuarioCorrecto, JSON_PRETTY_PRINT);
echo "\n\nAhora debería mostrar false: ";
$usuarioIncorrecto = autenticarUsuario("inexistente", "blabla");
echo json_encode($usuarioIncorrecto, JSON_PRETTY_PRINT);
echo "</pre>";

Igualmente dejo el código completo en mi GitHub. No olvides cambiar las credenciales de la base de datos. Aquí puedes leer más artículos de WordPress.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Ver comentarios

  • Buen post! Estoy tratando de hacer login con un usuario de Wordpress en un php externo, como el que has puesto. El caso es que, he probado lo que mencionas y nos muestras en el post pero no me funciona (he cambiado el usuario + passwd evidentemente). La salida de la web es esta:

    Debería mostrar los datos correctos: false
    Ahora debería mostrar false: false

    El login me funciona correctamente en el Wordpress..se te ocurre que puede ocurrir?

    Saludos!

Entradas recientes

Servidor HTTP en Android con Flutter

El día de hoy te mostraré cómo crear un servidor HTTP (servidor web) en Android…

4 días hace

Imprimir automáticamente todos los PDF de una carpeta

En este post te voy a enseñar a designar una carpeta para imprimir todos los…

5 días hace

Guía para imprimir en plugin versión 1 desde Android

En este artículo te voy a enseñar la guía para imprimir en una impresora térmica…

1 semana hace

Añadir tasa de cambio en sistema de información

Hoy te voy a mostrar un ejemplo de programación para agregar un módulo de tasa…

2 semanas hace

Comprobar validez de licencia de plugin ESC POS

Los usuarios del plugin para impresoras térmicas pueden contratar licencias, y en ocasiones me han…

2 semanas hace

Imprimir euro € en impresora térmica

Hoy voy a enseñarte cómo imprimir el € en una impresora térmica. Vamos a ver…

4 semanas hace

Esta web usa cookies.