Cómo validar un usuario desde fuera de WordPress/PHP

21 ene 2012, 15:32:29
Vistas: 17.5K
Votos: 10

Estoy trabajando en una aplicación AJAX que estará embebida en una página de WordPress. La aplicación AJAX intercambia datos con servlets ejecutándose en Tomcat. Ahora los servlets necesitan una forma de determinar si una petición viene de un usuario que está logueado en WordPress. Y si el usuario está logueado, los servlets también deben poder determinar el ID del usuario para poder consultar la base de datos. Si el usuario no está logueado, la petición será denegada.

En otras palabras, necesito que un servlet ejecute una petición solo si el usuario que la generó está logueado en WordPress (versión 3.3.x). Tanto el servlet (Tomcat) como WordPress (Apache2) corren en la misma máquina física y comparten la misma base de datos.

En teoría esto podría resolverse fácilmente haciendo lo siguiente:

  1. Durante el login de WordPress, algún token de usuario se almacena en una variable JavaScript.
  2. La aplicación AJAX envía el token de usuario a los servlets en cada llamada.
  3. Los servlets usan el token para consultar a WordPress si es válido (es decir, si el usuario está logueado) y ejecutan o deniegan la petición.

La pregunta es ¿cómo puede implementarse esto en el lado de WordPress?
Porque, lo que hace complicada la teoría es el hecho de que aún no he hecho programación en PHP.

Primero pensé en transmitir la cookie wordpress_logged_in (auth) al servlet y hacer que el servlet consulte a WordPress si la cookie auth sigue siendo válida. Pero al parecer, esto no puede hacerse, ya que wp_validate_auth_cookie() siempre falla, incluso si se pasan datos de cookie de un usuario logueado. Otra solución podría ser desarrollar un plugin que almacene el sessionid y userid en una tabla, que podría ser consultada fácilmente por los servlets. O quizás haya otra solución...

5
Comentarios

¿Por qué no escribir o usar un plugin que ofrezca autenticación de usuario como un servicio AJAX? Podría utilizar toda la pila de WP, y cualquier aplicación podría usarlo realizando una petición HTTP adecuada. Sin embargo, asegúrate de proteger apropiadamente las credenciales de tus usuarios.

Raphael Raphael
21 ene 2012 19:00:48

Creo que me expresé mal, no necesito un servicio de autenticación AJAX. Lo que necesito es una forma de permitir que un servlet valide un usuario ya autenticado. Es decir, verificar si el usuario sigue conectado. El punto es este: El usuario inicia sesión, accede a una aplicación AJAX, que se comunica con el servlet para almacenar/recuperar datos. Ahora el servlet necesita alguna forma de 1) probar si la solicitud proviene de un usuario conectado y 2) recuperar el ID del usuario (para mayor acceso a la base de datos).

Davos Seaworth Davos Seaworth
21 ene 2012 23:05:46

Tal vez deberías editar tu pregunta para incorporar todos esos comentarios. Preferiblemente, presenta tu problema (!) y cuál es tu idea. En particular, proporciona una descripción clara paso a paso del proceso que tienes en mente.

Raphael Raphael
22 ene 2012 00:33:20

Espero que la pregunta sea más clara ahora.

Davos Seaworth Davos Seaworth
22 ene 2012 01:30:46

¿cómo terminaste haciéndolo? ¿podrías compartir tu solución? ¿usaste XMLRPC?

Philipp Kyeck Philipp Kyeck
20 abr 2012 13:33:22
Todas las respuestas a la pregunta 5
2

WordPress ya tiene una API incorporada a través de un servidor XMLRPC. Esto significa que puedes hacer una solicitud XMLRPC desde tu aplicación Java y verificar un nombre de usuario/contraseña. Desafortunadamente, no hay manera de autenticarse directamente a través de ella tal como está.

Dicho esto, es muy fácil crear la tuya propia. Solo debes engancharte al filtro xmlrpc_methods y agregar el tuyo. La clave del array que agregues será el método XMLRPC que llamarás desde tu aplicación, y el valor será la función que será llamada por el servidor XMLRPC de WordPress.

<?php
add_filter('xmlrpc_methods', 'wpse39662_add_login_method' );
/**
 * Filtra los métodos XMLRPC para permitir solo verificar el usuario/contraseña
 * de un usuario dado
 */
function wpse39662_add_login_method( $methods )
{
    $methods['wpse39662.login'] = 'wpse39662_check_login';
    return $methods;
}

Y la función de callback, wpse39662_check_login, recibiría un argumento, el array de cosas enviadas al servidor XMLRPC.

<?php
function wpse39662_check_login( $args )
{
    $username = $args[0];
    $password = $args[1];

    $user = wp_authenticate( $username, $password );

    if( is_wp_error( $user ) )
    {
        return false;
    }
    return true;
}

Aquí está todo eso como un plugin. Con eso instalado y XMLRPC habilitado en tu sitio de WP, deberías poder hacer solicitudes con algún cliente XMLRPC (estoy seguro de que Java tiene uno).

Aquí está el código que usé para probar lo anterior (cliente XMLRPC de Python).

>>> import xmlrpclib as xmlrpc
>>> s = xmlrpc.ServerProxy('http://wordpress.dev/xmlrpc.php')
>>> s.wpse39662.login('admin', 'password')
True
21 ene 2012 18:54:30
Comentarios

¡Gracias! ¡Esto me acerca un gran paso! ¿Se puede lograr lo mismo usando la cookie de autenticación del usuario? Así no tengo que almacenar y enviar el nombre de usuario/contraseña a través de la red. Mi proyecto consiste en una aplicación AJAX que está incrustada en una página de WordPress. La aplicación AJAX llama a un servlet y el servlet pregunta a WordPress si el usuario está autenticado. Podría pasar el usuario/contraseña a la aplicación AJAX y transferirlo al servlet, pero me preocupa que no sea muy seguro. Así que intenté pasar el contenido de la cookie de autenticación a wp_validate_auth_cookie() pero siempre falla.

Davos Seaworth Davos Seaworth
21 ene 2012 20:39:42

Simplemente generaría un token o algo similar para el usuario y lo almacenaría en ambos extremos del sistema. Luego pasaría el token de un lado a otro.

chrisguitarguy chrisguitarguy
22 ene 2012 05:31:27
0

WordPress (actualmente) verifica si el usuario sigue conectado comprobando una de las cookies que emite al iniciar sesión. Construye el contenido de esta cookie mediante operaciones de hashing. Los detalles están en la función "wp_generate_auth_cookie" en /wp-includes/pluggable.php:

function wp_generate_auth_cookie($user_id, $expiration, $scheme = 'auth') {
    $user = get_userdata($user_id);

    $pass_frag = substr($user->user_pass, 8, 4);

    $key = wp_hash($user->user_login . $pass_frag . '|' . $expiration, $scheme);
    $hash = hash_hmac('md5', $user->user_login . '|' . $expiration, $key);

    $cookie = $user->user_login . '|' . $expiration . '|' . $hash;

    return apply_filters('auth_cookie', $cookie, $user_id, $expiration, $scheme);
}

Puedes recrear este algoritmo (usando esta y otras funciones de auth_cookie) en tu código Java para realizar las mismas verificaciones. Se podría usar JS para asegurar que la cookie se envía a tu servlet.

Alternativamente, XMLRPC podría ser una buena opción. Podrías escribir un nuevo método (como se explica en otra solución aquí) para validar la cookie de autenticación (en lugar de validar usuario y contraseña como se hace normalmente).

25 jul 2012 19:23:10
0

Obtén el plugin Exec-PHP, y luego crea una página en WordPress (no una entrada) con un permalink adecuado (http://misitio/user_id/) y el código de la referencia de la API get_current_user_id():

<?php
$user_id = get_current_user_id();
if ($user_id == 0) {
    echo 'Actualmente no has iniciado sesión.';
} else {
    echo 'Has iniciado sesión como usuario '.$user_id.'.';
}
?>

Luego puedes extraer las cookies que el cliente te envía y colocarlas en una solicitud GET para http://127.0.0.1/user_id/. Así sabrás si el usuario ha iniciado sesión y cuál es su ID de usuario.

16 jun 2013 00:18:48
3

Podrías hacer algo como esto en las páginas que no son de WordPress:

<?php
require('./wp-blog-header.php');
// Asegúrate de que ^ apunte al directorio raíz de tu instalación de WP

if ( is_user_logged_in() ) {
   // Ejecuta tu solicitud aquí
}

?>
21 ene 2012 16:49:47
Comentarios

Gracias por la respuesta, el problema es que los servlets están escritos en Java, por lo que no se puede ejecutar código PHP. Lo que estoy buscando es algún tipo de interfaz externa que permita a un servlet/Java comunicarse con WordPress/PHP. Seguro que existe algún tipo de interfaz disponible, simplemente no he podido encontrarla...

Davos Seaworth Davos Seaworth
21 ene 2012 17:01:52

Ah, ya veo. Quizás usar algo como Quercus http://www.caucho.com/resin-3.0/quercus/ podría darte lo mejor de ambos mundos?

FlashingCursor FlashingCursor
21 ene 2012 17:11:54

Gracias, pero Quercus no es la solución correcta, ya que ya tengo una instalación funcional de WordPress/PHP/Apache y una instalación funcional de servlet/Java/Tomcat. Lo único que necesito ahora es una interfaz entre estos dos que permita al servlet verificar si un usuario ha iniciado sesión en WordPress (algún tipo de interfaz/protocolo/IPC/lo que sea).

Davos Seaworth Davos Seaworth
21 ene 2012 18:04:45
0

Este es un plugin de WordPress de un solo archivo que hace el trabajo:

function yournamespace_validateAuthCookie($cookie, $scheme = 'logged_in') {
    return wp_validate_auth_cookie($cookie, $scheme);
}

function yournamespace_new_xmlrpc_methods($methods) {
    $methods['yournamespace.validateAuthCookie'] = 'yournamespace_validateAuthCookie';
    return $methods;
}
add_filter('xmlrpc_methods', 'yournamespace_new_xmlrpc_methods');

Básicamente, expone un nuevo método XML-RPC con el que puedes pedirle a WordPress que valide la cookie wordpress_logged_in_....

Luego necesitas escribir algún código para consultar este método y pasarle el valor de la cookie wordpress_logged_in_....

Este método devolverá false (si la cookie no es válida) o el ID de usuario si la validación es exitosa.

4 mar 2015 22:13:59