¿Cómo inicio sesión programáticamente en un usuario?

41

Estoy buscando la API que me permita iniciar sesión en un usuario pasándole el nombre de usuario y la contraseña. ¿Alguien tiene experiencia con esto?

Para aclarar, estoy tratando de hacer un cuadro de inicio de sesión AJAX que aparezca como una ventana emergente en la página de inicio, y no actualice la página en caso de credenciales incorrectas, pero solo si el inicio de sesión es correcto. Entonces, esto es lo que he hecho hasta ahora:

Actualizar

Ahora cargo el formulario de inicio de sesión en mi página de inicio, luego, al enviarlo, lanzo una solicitud AJAX que envía credenciales a este script:

function user_login_submit_try() {
  global $user;  

  $uid = user_authenticate($_POST['name'],$_POST['pass']);    
  $arr = array ('name'=>$_POST['name'],'pass'=>$_POST['pass']);
  if ($uid){
    $user = user_load($uid);
    user_login_finalize($arr);
  }

  echo drupal_json_encode($uid); 
  exit;
}; 

Hasta ahora funciona, pero mis preocupaciones son (como lo menciona googletorp) problemas de seguridad; parece que ninguna de las API que utilicé en este script desinfectó los datos de ninguna manera.

¿Alguien vería una mejor manera de hacerlo?

sedaadmin
fuente
¿Por qué motivo necesitaría iniciar sesión en un usuario desde el código con nombre de usuario y contraseña?
kiamlaluno
@ kiamlaluno Porque necesito usar Ajax en el formulario de inicio de sesión. En mis preguntas anteriores: drupal.stackexchange.com/questions/5780/… drupal.stackexchange.com/questions/5781/… No pude resolver ninguno de estos dos problemas, así que solicité un ajax personalizado.
silkAdmin

Respuestas:

33

Esto podría ayudar a alguien:

function mymodule_user_login_credentials($username, $password)
{
    if(user_authenticate($username, $password))
    {
      $user_obj = user_load_by_name($username);
      $form_state = array();
      $form_state['uid'] = $user_obj->uid;      
      user_login_submit(array(), $form_state);
      return true;
    }
    else
    {
        return false;
    }
}

Una mejor versión basada en el comentario:

function mymodule_user_login_credentials($username, $password)
{
    if($uid = user_authenticate($username, $password))
    {
      user_login_submit(array(), array('uid' => $uid));
      return true;
    }
    else
    {
        return false;
    }
}
usuario1750
fuente
3
user_authenticate ya devuelve $ uid, por lo que no es necesario cargar el objeto de usuario;)
VUELO el
77
El segundo bloque de código no funcionará; El segundo argumento de user_login_submit se pasa por ref; al pasarlo, la salida de array () fallará.
Shawn Conn
¿Cómo se usaría esta respuesta para iniciar sesión automáticamente a un usuario después de haber sido creado usando un formulario de registro? Me gustaría hacer eso, pero la contraseña es un hash cuando se proporciona a través del objeto de cuenta como parámetro, hook_user_insertpero las funciones anteriores en la respuesta quieren la contraseña como texto plano original. Creo que voy a necesitar para tratar hook_form_altersu lugar ...
therobyouknow
Para las personas que buscan un inicio de sesión automático directamente después de que se haya creado el nuevo usuario (por ejemplo, mediante un formulario de registro de registro de usuario, por ejemplo, 'usuario / registro'), consulte esta solución: drupal.stackexchange.com/a/254905/1082
therobyouknow
19

No hay una función API simple para eso.

Puedes hacer lo que hace Drupal:

  1. Pruebe la contraseña consultando la base de datos, consulte:

user_login_name_validate ()
user_login_authenticate_validate ()
user_login_final_validate ()

  1. Sobrescribir el global $user.

    global $user;
    $user = user_load($uid);
  2. Manejar sesiones

user_login_finalize($form_state);

Para el paso dos y 3 ver user_login_submit()

Todas estas funciones se basan en ser llamadas desde un formulario. El flujo normal es que los manejadores de validación prueban la entrada de los usuarios y devuelven el uid del usuario si la validación pasa. El controlador de envío maneja el inicio de sesión real del usuario y el enlace del usuario llamante.

googletorp
fuente
gracias googletorp, lo probaré, aunque esto me permite preguntarme cómo funcionan juntas estas funciones. ¿Cómo se sabe que invoqué el precedente?
silkAdmin
Ah, y si no tengo la variable availlable From_state pero sólo nombre de usuario y contraseña, puedo reconstruirla como: $form_state['value']['name'] = $_POST['name']y así sucesivamente ..
silkAdmin
@silk Siempre debe usar el Drupal FAPI que le da la $form_statevariable. Hay muchas comprobaciones de seguridad agradables que de otro modo perdería y posiblemente abriría su sitio para ataques. Cuando se trata de iniciar sesión en un usuario, no desea perder esa seguridad.
googletorp
Por favor revise mi pregunta actualizada, realmente me gustaría saber si mis entradas se limpian .. Gracias
silkAdmin
Lo sentimos, parece que la edición no funcionó la primera vez, ahora está actualizada.
silkAdmin
7

Si necesita obtener el objeto de usuario para la cuenta de usuario para la que conoce el nombre de usuario y la contraseña, puede usar el siguiente código:

function mymodule_get_user(name, $password) {
  $account = FALSE;

  if ($uid = user_authenticate($name, $password)) {
    $account = user_load($uid);
  }

  return $account;
}

$accountserá FALSEsi el objeto de usuario no se puede encontrar o cargar.

Debe usar este código cuando, por ejemplo, su módulo obtiene el nombre de usuario y la contraseña como entrada de un usuario, verifica si son correctos y luego hace algo con el objeto de usuario.
Si está escribiendo un módulo que necesita hacerse pasar por un usuario para escribir un comentario, o está haciendo otra cosa que debe resultar como lo hizo un usuario, que es lo que hace el módulo de seguimiento de problemas del proyecto al cerrar un informe de problemas que ha estado en el estado fijo durante dos semanas (en ese caso, agrega el comentario "Automáticamente cerrado - problema solucionado por 2 semanas sin actividad" que resulta escrito por el usuario "Mensaje del sistema"), entonces no necesita nombre de usuario y contraseña. Simplemente carga el objeto de usuario para el que conoce la ID de usuario.

Hasta donde sé, no hay ningún problema de seguridad con el código que informé.
Es posible que desee limitar el número de inicios de sesión fallidos; o para bloquear temporalmente la IP que intenta iniciar sesión sin éxito, o intenta diferentes inicios de sesión en poco tiempo.

kiamlaluno
fuente
gracias kiamlaluno, es algo de lo que hice, pero ahora estoy preocupado por problemas de seguridad, por favor revise mi pregunta actualizada
silkAdmin
3

Este código realmente funciona

//login
$uid = user_authenticate($username, $password);
global $user;
$user = user_load($uid);    
//login finalize
watchdog('remote_user', 'Session opened for %name.', array('%name' => $user->name));
$user->login = REQUEST_TIME;
db_update('users')
  ->fields(array('login' => $user->login))
  ->condition('uid', $user->uid)
  ->execute();
drupal_session_regenerate();
vacho
fuente
No invoca hook_user_login, vea la función user_login_finalize ().
skorzh
2

Respuesta limpia de lo anterior. La comprobación de usuario y contraseña es una característica adicional. Además, el form_state falso debe ser una variable que se pase por referencia a la función o arrojará un error.

Por lo tanto tenemos:

function mymodule_log_in_by_uid($uid) {
    $faux_form_state = array('uid' => $uid);
    user_login_submit(array(), $faux_form_state);
}
Jeremy John
fuente
0

El usuario recibirá la sesión y también iniciará sesión en otras páginas:

function custom_log_in_by_uid($uid) {
    $form_state = array('uid' => $uid);
    user_login_submit(array(), $form_state);
}
Віктор Плясун
fuente
0

A veces necesitamos un inicio de sesión rápido desde URL u Olvidé mi contraseña de administrador. Simplemente implemente a continuación dos funciones para iniciar sesión como usuario 1 en Drupal.

function mymodule_menu(){
    $items['login/as/admin'] = array(
        'title' => 'Login as admin account',
        'page callback' => 'mymodule_login_as_admin',
        'access callback' => TRUE,
        'type' => MENU_CALLBACK,
    );
    return $items;
}
function mymodule_login_as_admin(){
    global $user;
    $user = user_load(1);
    return "Global user set as admin. Please refresh page ";
}
Bathyal Girish
fuente