Jak mogę programowo zalogować użytkownika?

41

Szukam interfejsu API, który pozwoli mi zalogować się do użytkownika, przekazując mu nazwę użytkownika i hasło. Czy ktoś ma z tym doświadczenie?

Aby to wyjaśnić, próbuję utworzyć pole logowania AJAX, które pojawi się jako wyskakujące okienko na stronie głównej, i nie odświeżaj strony w przypadku nieprawidłowych poświadczeń, ale tylko wtedy, gdy logowanie jest prawidłowe. Oto co zrobiłem do tej pory:

Aktualizacja

Teraz ładuję formularz logowania na mojej stronie głównej, a po przesłaniu uruchamiam żądanie AJAX, które wysyła poświadczenie do tego skryptu:

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

Jak dotąd działa, ale moje obawy dotyczą (jak wspomniano w googletorp) problemów bezpieczeństwa; Wygląda na to, że żaden interfejs API użyty w tym skrypcie i tak nie zdezynfekował danych.

Czy ktoś widziałby lepszy sposób?

silkAdmin
źródło
Z jakiego powodu musiałbyś zalogować użytkownika z kodu przy użyciu nazwy użytkownika i hasła?
kiamlaluno
@ kiamlaluno Ponieważ muszę użyć Ajax w formularzu logowania. W moich poprzednich pytaniach: drupal.stackexchange.com/questions/5780/… drupal.stackexchange.com/questions/5781/... Nie mogłem rozwiązać żadnego z tych dwóch problemów, więc wybrałem niestandardowe żądanie ajax.
silkAdmin

Odpowiedzi:

33

To może pomóc komuś:

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

Lepsza wersja oparta na komentarzu:

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;
    }
}
użytkownik1750
źródło
3
user_authenticate już zwraca $ uid, więc nie trzeba ładować obiektu użytkownika;)
FLY
7
Drugi blok kodu nie będzie działał; drugi argument użytkownika user_login_submit jest przekazywany przez ref; przekazanie go zakończy się niepowodzeniem.
Shawn Conn
W jaki sposób można by użyć tej odpowiedzi do automatycznego logowania użytkownika po utworzeniu go za pomocą formularza rejestracyjnego? Chciałbym to zrobić, ale hasło jest skrótem, gdy jest przekazywane przez obiekt konta jako parametr, hook_user_insertale powyższe funkcje w odpowiedzi wymagają hasła jako oryginalnego zwykłego tekstu. Chyba będę musiał spróbować hook_form_alterzamiast tego ...
therobyouknow
Osoby szukające automatycznego logowania bezpośrednio po utworzeniu nowego użytkownika (np. Za pomocą formularza rejestracji użytkownika, np. „Użytkownik / rejestr”), zobacz to rozwiązanie: drupal.stackexchange.com/a/254905/1082
therobyouknow
19

Nie ma do tego prostej funkcji API.

Możesz robić to, co robi Drupal:

  1. Sprawdź hasło, sprawdzając bazę danych, patrz:

user_login_name_validate ()
user_login_authenticate_validate ()
user_login_final_validate ()

  1. Zastąp plik global $user.

    global $user;
    $user = user_load($uid);
  2. Obsługuj sesje

user_login_finalize($form_state);

Krok drugi i trzeci patrz user_login_submit()

Wszystkie te funkcje opierają się na wywołaniu z formularza. Normalny przepływ polega na tym, że procedury sprawdzania poprawności testują dane wejściowe użytkowników i zwracają identyfikator użytkownika, jeśli sprawdzanie poprawności się powiedzie. Program obsługi przesyłania obsługuje następnie rzeczywiste logowanie użytkownika i wywoływanie haka użytkownika.

googletorp
źródło
dzięki googletorp, spróbuję tego, chociaż to pozwala mi się zastanawiać, jak te funkcje działają razem. Skąd wiadomo, że powołałem się na precedens?
silkAdmin,
och, a jeśli nie mam dostępnej zmiennej From_state, ale tylko nazwę użytkownika i hasło, czy mogę je odbudować w następujący sposób: $form_state['value']['name'] = $_POST['name']itd.
silkAdmin,
@silk Powinieneś zawsze używać interfejsu Drupal FAPI, który daje ci $form_statezmienną. Istnieje wiele fajnych kontroli bezpieczeństwa, które w przeciwnym razie można by stracić i otworzyć witrynę na ataki. Jeśli chodzi o logowanie użytkownika, nie chcesz stracić tego bezpieczeństwa.
googletorp
Proszę sprawdzić moje zaktualizowane pytanie, naprawdę chciałbym wiedzieć, czy moje dane wejściowe zostaną oczyszczone. Dzięki
silkAdmin,
Niestety wygląda na to, że edycja nie działała za pierwszym razem, teraz jest aktualizowana.
silkAdmin
7

Jeśli potrzebujesz uzyskać obiekt użytkownika dla konta użytkownika, dla którego znasz nazwę użytkownika i hasło, możesz użyć następującego kodu:

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

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

  return $account;
}

$accountbędzie, FALSEjeśli nie można znaleźć lub załadować obiektu użytkownika.

Powinieneś użyć tego kodu, gdy na przykład moduł pobiera nazwę użytkownika i hasło jako dane wejściowe od użytkownika, sprawdza, czy są poprawne, a następnie robi coś z obiektem użytkownika.
Jeśli piszesz moduł, który musi podszyć się pod użytkownika, aby napisać komentarz, lub robisz coś innego, co musi zostać wykonane przez użytkownika, to właśnie robi moduł śledzenia problemów z projektem przy zamykaniu raportu o problemach, który był w naprawiono status na dwa tygodnie (w takim przypadku dodaje się komentarz „Automatycznie zamknięty - problem naprawiony przez 2 tygodnie bez aktywności”, którego wyniki napisał użytkownik „Wiadomości systemowej”), wtedy nie potrzebujesz nazwy użytkownika i hasła. Po prostu ładujesz obiekt użytkownika, dla którego znasz identyfikator użytkownika.

O ile mi wiadomo, nie ma żadnych problemów z bezpieczeństwem w zgłoszonym kodzie.
Możesz ograniczyć liczbę nieudanych prób logowania; lub tymczasowe zablokowanie adresu IP, który próbuje się zalogować bez powodzenia, lub próbuje różnych logowań w krótkim czasie.

kiamlaluno
źródło
dziękuję kiamlaluno, tak jakby to zrobiłem, ale teraz martwię się o kwestie bezpieczeństwa, proszę sprawdź moje zaktualizowane pytanie
silkAdmin
3

Ten kod naprawdę działa

//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
źródło
Nie wywołuje funkcji hook_user_login, patrz funkcja user_login_finalize ().
skorzh
2

Oczyszczona odpowiedź z powyższego. Sprawdzanie użytkownika i hasła to dodatkowa funkcja. Ponadto fałszywy parametr form_state musi być zmienną, która ma być przekazywana przez odwołanie do funkcji, w przeciwnym razie generuje błąd.

Dlatego mamy:

function mymodule_log_in_by_uid($uid) {
    $faux_form_state = array('uid' => $uid);
    user_login_submit(array(), $faux_form_state);
}
Jeremy John
źródło
0

Użytkownik otrzyma sesję i zostanie również zalogowany na innych stronach:

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

Czasami potrzebujemy szybkiego logowania z adresu URL lub zapomniałem hasła administratora. Wystarczy zaimplementować poniżej dwie funkcje, aby zalogować się jako użytkownik 1 w 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
źródło