Como faço logon programaticamente em um usuário?

41

Estou procurando a API que permitirá que eu entre com um usuário, passando o nome de usuário e a senha. Alguém tem experiência com isto?

Para esclarecer, estou tentando criar uma caixa de login do AJAX que apareça como um pop-up na página inicial e não atualize a página no caso de credenciais incorretas, mas apenas se o login estiver correto. Então, aqui está o que eu fiz até agora:

Atualizar

Agora, carrego o formulário de login na minha página inicial e, após o envio, inicio uma solicitação AJAX que envia credencial para 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;
}; 

Até agora, funciona, mas minhas preocupações são (como mencionado pelo googletorp) problemas de segurança; parece que nenhuma das API que usei nesse script higienizou os dados de qualquer maneira.

Alguém veria uma maneira melhor de fazer isso?

silkAdmin
fonte
Por que motivo você precisaria fazer login em um usuário a partir do código usando nome de usuário e senha?
kiamlaluno
@ kiamlaluno Porque eu preciso usar o Ajax no formulário de login. Nas minhas perguntas precedentes: drupal.stackexchange.com/questions/5780/… drupal.stackexchange.com/questions/5781/… Não consegui resolver nenhum desses dois problemas, então solicitei um ajax personalizado.
silkAdmin

Respostas:

33

Isso pode ajudar alguém:

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;
    }
}

Uma versão melhor baseada no comentário:

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;
    }
}
user1750
fonte
3
já user_authenticate retorna a $ uid assim não há necessidade para carregar o objeto de usuário;)
FLY
7
O segundo bloco de código não funcionará; O segundo argumento de user_login_submit é passado por ref; passando a saída de array () falhará.
Shawn Conn
Como essa resposta seria usada para fazer o login automático de um usuário depois que ele foi criado usando um formulário de registro? Eu gostaria de fazer isso, mas a senha é um hash quando fornecida pelo objeto de conta como parâmetro, hook_user_insertmas as funções acima na resposta desejam a senha como texto sem formatação original. Eu acho que vou precisar tentar hook_form_alter...
therobyouknow
Para pessoas que procuram o login automático diretamente após a criação do novo usuário (por exemplo, através de um formulário de registro de inscrição do usuário, por exemplo, 'usuário / registro'), consulte esta solução: drupal.stackexchange.com/a/254905/1082
therobyouknow
19

Não existe uma função API simples para isso.

Você pode fazer o que o Drupal faz:

  1. Teste a senha consultando o banco de dados, consulte:

user_login_name_validate ()
user_login_authenticate_validate ()
user_login_final_validate ()

  1. Substitua o global $user.

    global $user;
    $user = user_load($uid);
    
  2. Lidar com sessões

user_login_finalize($form_state);

Para os passos dois e 3, consulte user_login_submit()

Todas essas funções são baseadas em chamadas de um formulário. O fluxo normal é que os manipuladores de validação testam a entrada dos usuários e retornam o uid do usuário se a validação for aprovada. O manipulador de envio lida com o logon real do usuário e com o gancho do usuário que está chamando.

googletorp
fonte
obrigado googletorp, tentarei isso, embora isso me permita pensar em como essas funções funcionam juntas. Como alguém sabe que invoquei o precedente?
silkAdmin
Ah, e se eu não tiver o availlable variável From_state mas apenas usuário e senha, posso reconstruí-lo como: $form_state['value']['name'] = $_POST['name']e assim por diante ..
silkAdmin
@silk Você sempre deve usar o Drupal FAPI, que fornece a $form_statevariável. Existem muitas verificações de segurança legais que você perderia e, possivelmente, abriria o site para ataques. Quando se trata de fazer login em um usuário, você não quer perder essa segurança.
googletorp
Por favor, verifique a minha pergunta atualizadas, eu realmente gostaria de saber se as minhas entradas de se limpar .. Obrigado
silkAdmin
Desculpe, parece que a edição não funcionou da primeira vez, agora está atualizada.
silkAdmin
7

Se você precisar obter o objeto de usuário para a conta de usuário cuja senha e nome de usuário você conhece, poderá usar o seguinte código:

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

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

  return $account;
}

$accountserá FALSEse o objeto do usuário não puder ser encontrado ou carregado.

Você deve usar esse código quando, por exemplo, seu módulo obtiver o nome de usuário e a senha como entrada de um usuário, verificar se eles estão corretos e fazer algo com o objeto de usuário.
Se você estiver escrevendo um módulo que precisa se passar por um usuário para escrever um comentário ou fazer algo que precise resultar como feito por um usuário, é o que o módulo de rastreamento de problemas do Projeto faz ao fechar um relatório de problemas que está no diretório status fixo por duas semanas (nesse caso, ele adiciona o comentário "Problema resolvido automaticamente por 2 semanas sem atividade", que resulta escrito pelo usuário "Mensagem do sistema"), então você não precisa de nome de usuário e senha. Você acabou de carregar o objeto de usuário para o qual você conhece o ID do usuário.

Até onde eu sei, não há problemas de segurança com o código que relatei.
Você pode querer limitar o número de logins com falha; ou bloquear temporariamente o IP que tenta efetuar login sem êxito ou tenta logins diferentes em pouco tempo.

kiamlaluno
fonte
obrigado kiamlaluno, meio que o que eu fiz, mas eu estou agora se preocupar com questões de segurança, confira a minha pergunta atualizados
silkAdmin
3

Esse 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
fonte
Ele não chama hook_user_login, consulte a função user_login_finalize ().
Skorzh
2

Resposta limpa do acima. Verificar usuário e senha é um recurso adicional. Além disso, o false form_state precisa ser uma variável a ser passada por referência à função ou gera um erro.

Portanto, temos:

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

O usuário receberá a sessão e também fará logon em outras páginas:

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

Às vezes, precisamos de login rápido a partir da URL ou Esqueci a senha do administrador. Basta implementar abaixo de duas funções para fazer login como usuário 1 no 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 ";
}
Girish Bathyal
fonte