Cómo verificar usuario/contraseña sin iniciar sesión del usuario

9 ago 2012, 18:39:28
Vistas: 25.7K
Votos: 6

Estoy escribiendo un plugin que crea un endpoint de API que valida pares de usuario/contraseña.

Actualmente estoy usando wp_signon() para verificar si la combinación de usuario/contraseña funciona. Esto funciona bien cuando las credenciales fallan porque devuelve un objeto de error. Pero cuando las credenciales son correctas, automáticamente inicia sesión con ese usuario, por lo que mi endpoint devuelve una página completa.

El codex actualmente ni siquiera menciona el hecho de que automáticamente inicia sesión del usuario. Tampoco parece aceptar un parámetro para suprimir esa funcionalidad. Para mis propósitos un simple booleano estaría bien.

ACTUALIZACIÓN: Tuve que elegir una única respuesta, pero había mucha información útil en varias de las otras respuestas que intentaré resumir brevemente aquí...

  1. EXISTE una función que hace exactamente lo que estaba tratando de hacer: wp_authenticate($username, $password) SIN EMBARGO, viene con una desventaja. Establecerá automáticamente las cookies de inicio de sesión, lo que puede crear problemas en una situación como la mía. Así que ten cuidado. Esta función no está actualmente en el codex.

  2. La mejor opción para lo que estoy haciendo es wp_authenticate_username_password($user, $username, $password) porque NO establece las cookies de inicio de sesión. Esta función está más documentada, pero el detalle REALMENTE importante que no estaba en el codex es que puedes pasar NULL como primer parámetro. Esto significa que puedes efectivamente usarla para hacer exactamente como wp_authenticate() sin preocuparte de que las cookies se estropeen. Lee la documentación para que no te confundas con la respuesta. Devuelve un objeto WP_User o un WP_Error (¡no un booleano!).

4
Comentarios

El Codex es impulsado por los usuarios. Solo inicia sesión y cambia/edita/agrega lo que consideres que falta. (Míralo como miras Wikipedia).

kaiser kaiser
9 ago 2012 19:55:26

Nota: wp_authenticate no establece realmente las cookies de inicio de sesión, eso ocurre en wp_signon. Sin embargo, wp_authenticate aplicará todos los métodos de autenticación enganchados, por lo que si se envía una auth-cookie válida con la solicitud, puede validar al usuario independientemente del nombre de usuario/contraseña. Si solo quieres verificar el nombre de usuario y contraseña, wp_authenticate_username_password es efectivamente correcto.

Otto Otto
14 ago 2012 00:52:06

¿llegaste a publicar este plugin/endpoint?

lofidevops lofidevops
25 oct 2017 01:02:20

@d3vid Esto era para un proyecto privado de hace años, así que el código necesitaría actualizarse para ser compatible con la versión actual de WP. Pero si esto es algo que te interesa, envíame un correo.

emersonthis emersonthis
25 oct 2017 01:35:08
Todas las respuestas a la pregunta 4
4
10

Hay una función en los user.php de los archivos principales llamada wp_authenticate_username_password que parece ser lo que estás buscando.

Si deseas evitar pasar el objeto $user (probablemente solo tengas el nombre de usuario + contraseña), entonces simplemente pasa null como primer argumento de la función:

$check = wp_authenticate_username_password( NULL, 'some_username', '#thepassw0rd' );

Luego puedes verificar el resultado simplemente con is_wp_error( $check ).

9 ago 2012 19:15:15
Comentarios

Esto no hace lo que parece. Es un error común (que yo también he cometido). Sin embargo, acabo de descubrir una función que realmente hace lo que queremos. Mira mi respuesta...

emersonthis emersonthis
9 ago 2012 19:54:24

+1 parece ser la forma perfecta. Espero que no te importe la edición.

kaiser kaiser
9 ago 2012 19:54:29

@kaiser "Vaya". Nunca me di cuenta de que podías pasar NULL como primer parámetro. Es bueno saberlo. También echa un vistazo a wp_authenticate() (ver mi respuesta). Lo acabo de encontrar después de semanas de búsqueda.

emersonthis emersonthis
9 ago 2012 20:03:58

Definitivamente la forma más eficiente.

Adam Adam
9 ago 2012 20:04:20
1

Usa,

y

Explicación

// obtener usuario por login mediante el nombre de usuario proporcionado (input del formulario)
$user = get_user_by('login', $username);

// asignar ID de usuario basado en el nombre de login
$user_id = $user->ID;

// obtener datos del usuario pasando la variable $user_id a get_userdata
// que devuelve el objeto de usuario y gran cantidad de información relacionada para acceder
$user_data = get_userdata($user_id);


// asignar el nombre de usuario y contraseña a variables
$user_login = $user_data->user_login;
$user_pass = $user_data->user_pass;

// verificar el nombre de usuario/contraseña contra los valores enviados
if ($user_login = $username && $user_pass = $password) {

// hacer algo...

Notas

  • $username debería validarse como verdadero por defecto, de lo contrario no se habría devuelto un objeto de usuario si el $username proporcionado no coincidía con uno existente en la base de datos. Por lo tanto, la validación depende entonces de la variable $password que almacena el input del formulario proporcionado por el usuario.

  • Podría haber una forma más eficiente de lograr esto, ya sea acortando el código existente o usando otras funciones de la API.

ACTUALIZACIÓN

Basado en la sugerencia de fdsa podrías usar wp_authenticate_username_password de esta manera,

$auth = wp_authenticate_username_password($user, $username, $password);

if (!$auth->user_login = $username && !$auth->user_pass = $password) {

echo 'no autenticado';

} else {

echo 'autenticado';

}

Pero incluso mejor que eso,

$auth = wp_authenticate_username_password($user, $username, $password);

if (is_wp_error($auth)) {

echo 'no autenticado';

} else {

echo 'autenticado';

}

Realmente el crédito/respuesta marcada debería darse a fdsa por el método más eficiente mediante una función (tristemente) no documentada del núcleo de WP.

http://wpseek.com/wp_authenticate_username_password/

9 ago 2012 19:12:55
Comentarios

Esto es genial. Pero get_userdata devolverá la contraseña cifrada (no el texto plano). ¿Algún consejo sobre cómo evitar esto?

emersonthis emersonthis
9 ago 2012 19:33:47
0

Descargo de responsabilidad: Esta respuesta solo pretende mostrar lo que ocurre detrás de escena y no es un ejemplo real de cómo hacer las cosas.


Traza de ejecución

wp_signon() llama a wp_set_auth_cookie(), que a su vez llama a wp_generate_auth_cookie(). El resultado se utilizará dentro de setcookie() como segundo argumento.

(No performante) diversión con filtros

También conocido como engañar a WordPress de la manera incorrecta.

Podrías entonces entrar en el filtro 'auth_cookie' dentro de wp_generate_auth_cookie() y simplemente establecerlo como nulo o algo diferente al valor de SECURE_AUTH_COOKIE o AUTH_COOKIE. Esto te dejará con una cookie sin sentido, que no puede iniciar sesión.

9 ago 2012 20:15:30
6

"¡Listo!": wp_authenticate($username, $password)

No aparece en el codex, pero puedes buscarlo en wpseek.

Hace exactamente lo que parece. Toma un nombre de usuario y contraseña en texto plano y devuelve ya sea un objeto WP_User o un WP_Error... y NO inicia sesión de nadie.

¡Una advertencia importante! Lo siguiente SIEMPRE devolverá verdadero (porque la función devuelve un objeto en cualquier caso):

$auth = ( wp_authenticate($username, $password) ) ? TRUE : FALSE;

Probablemente querrás hacer algo como esto:

$test_creds = wp_authenticate($username, $pass);
$class = get_class($test_creds);
$auth = ( $class == 'WP_User' ) ? TRUE : FALSE;

Espero que esto le ayude a alguien.

9 ago 2012 19:59:08
Comentarios

Puedes usar instanceof o is_a() para verificar si es un WP_User. También podrías simplemente usar una de las funciones anteriores y eliminar el filtro en authenticate...

kaiser kaiser
9 ago 2012 20:03:17

Se recomienda usar is_wp_error($auth) que devolverá TRUE si falla la autenticación y FALSE si la autenticación es exitosa.

Adam Adam
9 ago 2012 20:07:56

Una nota más: Esto no te iniciará sesión, pero aún así dejará la cookie establecida, ya que la función llama al filtro `'authenticate`. Si optas por esa solución, debes asegurarte de que se eliminen todas las devoluciones de llamada del filtro. De lo contrario, el cielo podría caerte encima :)

kaiser kaiser
9 ago 2012 20:20:21

Es bueno saberlo. ¿Acaso wp_authenticate_username_password( NULL, 'some_username', '#thepassw0rd' ); tiene el mismo problema? ¿Podrías elaborar un poco más sobre lo del "cielo cayéndose"? ¿Qué es lo que podría salir mal?

emersonthis emersonthis
9 ago 2012 20:56:20

Nota: En lugar de usar wp_authenticate, en realidad quieres usar user_pass_ok($user_login, $user_pass), que a su vez utiliza wp_authenticate ya que es la función envoltorio adecuada que devuelve true/false. Sin embargo, como dijo @kaiser, la cookie se establece mediante el filtro authenticate. La función wp_authenticate_username_password no parece establecer la cookie.

Adam Adam
9 ago 2012 21:02:33

Según la documentación, wp_authenticate() SÍ inicia sesión del usuario si las credenciales son correctas. Curiosamente, no lo hace en mi caso.

Gerald Schneider Gerald Schneider
25 jul 2013 10:16:01
Mostrar los 1 comentarios restantes