2012-01-18 29 views
15

Krótki

Praca z systemem logowania i próba zaimplementowania funkcji zapamiętaj mnie.Właściwy sposób używania funkcji "Zapamiętaj mnie" w PHP

Niedawno zrobiłem badania na ten temat, przeczytałem kilka artykułów, postów, opowiadań, powieści, baśni (nazywając je tak, ponieważ niektóre z nich nie zawierają nawet 1 linii kodu, tylko mnóstwo słów) o, luk ciasteczek, takich jak utrwalenie, porwania ... itd

i postanowił osiągnąć następujące cele

  1. aby ustawić opóźnienie pomiędzy prób logowania (aby zapobiec atakom Bruteforce) oraz ograniczyć próby liczyć
  2. Aby zregenerować identyfikator sesji przy prawie każdej operacji

Ale Naprawdę myliłem się z moim głównym problemem: jaki sposób jest właściwy, dla funkcji "zapamiętaj mnie"? korzystać z plików cookie/sesji/bazy danych?

I proszę wyjaśnić swój pomysł na kod. (Nie mogę zrozumieć jasno bez kodu)

Szczegółowe

Obecnie mój kod wygląda tak

Podczas logowania Używam Poniższa funkcja na ustawianie ciasteczek i sesji

protected function validateUser($userid, $ckey=0, $rememmber=0) { 
    session_start(); 
    session_regenerate_id(true); //this is a security measure 
    $_SESSION['user_id'] = $userid; 
    $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']); 
    if (isset($remember) && $rememmber == 'on') { 
     setcookie("user_id", $_SESSION['user_id'], time() + 60 * 60 * 24 * COOKIE_TIME_OUT, "/"); 
     setcookie("user_key", sha1($ckey), time() + 60 * 60 * 24 * COOKIE_TIME_OUT, "/"); 
    } 
    return true; 
} 

Następnie na bezpiecznych stronach użytkowników, sprawdzanie user_id użyciu user_id pobrać wszystkie ważne Dane na temat użytkownika z db

public function protect() { 
     session_start(); 

     /* Secure against Session Hijacking by checking user agent */ 
     if (isset($_SESSION['HTTP_USER_AGENT'])) { 
      if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT'])) { 
       $this->signout(); 
       exit; 
      } 
     } 

// before we allow sessions, we need to check authentication key - ckey and ctime stored in database 

     /* If session not set, check for cookies set by Remember me */ 
     if (!isset($_SESSION['user_id'])) { 
      if (isset($_COOKIE['user_id']) && isset($_COOKIE['user_key'])) { 
       /* we double check cookie expiry time against stored in database */ 

       $cookie_user_id = $_COOKIE['user_id']; 
           $stmt = $this->db->prepare("select `ckey`,`ctime` from `users` where `id` =?") or die($this->db->error); 
      $stmt->bind_param("i", $cookie_user_id) or die(htmlspecialchars($stmt->error)); 
      $stmt->execute() or die(htmlspecialchars($stmt->error)); 
      $stmt->bind_result($ckey, $ctime) or die($stmt->error); 
      $stmt->close() or die(htmlspecialchars($stmt->error)); 
       // coookie expiry 
       if ((time() - $ctime) > 60 * 60 * 24 * COOKIE_TIME_OUT) { 
        $this->signout(); 
       } 
       /* Security check with untrusted cookies - dont trust value stored in cookie.  
        /* We also do authentication check of the `ckey` stored in cookie matches that stored in database during login */ 

       if (!empty($ckey) && is_numeric($_COOKIE['user_id']) && $_COOKIE['key'] == sha1($ckey)) { 
        session_regenerate_id(); //against session fixation attacks. 

        $_SESSION['user_id'] = $_COOKIE['user_id']; 
        $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']); 
       } else { 
        $this->signout(); 
       } 
      } else { 
       if ($page != 'main') { 
        header('Location:' . wsurl); 
        exit(); 
       } 
      } 
     } 
+1

Tylko komentarz: Z punktu widzenia UX, jest to dobry moment, aby poinformować użytkowników, czy masz na myśli "keep me logged in", czy po prostu "zapamiętaj moją tożsamość". – PapaFreud

+0

Prawdopodobny duplikat: http://stackoverflow.com/questions/244882/what-is-the-best-way-to-implement-remember-me-for-site – ThinkingMonkey

+0

@ThinkingMonkey ok, jesteś cool :) –

Odpowiedz

2

Ale naprawdę myliłem się z moim głównym problemem: jaki sposób jest właściwy, dla funkcji "zapamiętaj mnie"? korzystać z plików cookie/sesji/bazy danych?

Http to bezpaństwowy protokół. Token uwierzytelniania musi się utrzymywać, aby zachować stan. Właściwym sposobem jest użycie sesji. Jak śledzisz sesję? To zależy od Ciebie. Ale ciasteczka nie są złe.

W sesji można zapisać hasz utworzony na podstawie różnych kryteriów przeglądarki (agent użytkownika, system operacyjny, rozdzielczość ekranu itp.), Aby sprawdzić, czy token pochodzi z tego samego środowiska. Im więcej kryteriów zapiszesz, tym trudniej będzie je przejąć. Btw potrzebujesz JavaScript, aby pobrać dodatkowe informacje za każdym razem.

+2

Nienawidzę zaniedbania, ale 'spróbuj wysłać go przez URL (wiem, że wygląda brzydko).' - jest naprawdę celem dla downvote. Jest to znana luka ** ** związana z atakami na pliki cookie –

3

Jeśli chcesz przykład „Remember Me” funkcji z kodu, można sprawdzić moją bibliotekę PHP w https://github.com/gbirke/rememberme

+0

Mam to działa na firefox. Ale na chrome twoje pliki testowe nie działają: pozostaje na pierwszej stronie, nie loguje się. –

+0

Czy mogę wziąć 5-10 minut? proszę dodać mnie tural.teyyuboglu w skype –

8

Aby ustawić opóźnienie pomiędzy prób logowania (Aby zapobiec atakom bruteforce) i ograniczyć liczbę prób, należy liczyć

Dostarczasz metodę DOS na konto?

Aby zregenerować identyfikator sesji na prawie każdej operacji

erm, no. To naprawdę może pokonać obiekt. Powinieneś zawsze generować nowy identyfikator, gdy bieżący identyfikator wygasł lub gdy użytkownik jest uwierzytelniony - w przeciwnym razie zostaw go w spokoju.

Ale naprawdę myliłem się z moim głównym problemem: jaki sposób jest właściwy, dla funkcji "zapamiętaj mnie"? korzystać z plików cookie/sesji/bazy danych?

Ponieważ musisz zachować token na kliencie, oznacza to ciasteczka (chyba że masz ochotę napisać coś naprawdę skomplikowanego za pomocą lokalnego magazynu). Ponieważ nie chcesz ujawniać danych za pomocą cookie/fałszować proste, oznacza to, że powinna być losowa wartość.Aby pogodzić przechowywaną losową wartość, oznacza to przechowywanie serwerów danych - prawdopodobnie w bazie danych, ponieważ musi istnieć możliwość odniesienia danych na podstawie identyfikatora użytkownika lub w oparciu o losową wartość.

Chociaż można użyć nieukończonej (lub bardzo długiej żywotności) sesji, trzymałbym się z daleka od tego - dane będą kulą śnieżną - i jest to dobry pomysł, aby odnawiać dane sesji raz na jakiś czas.

Musisz także przygotować scenariusz, w którym użytkownik chce, abyś pamiętał ją na dwóch różnych komputerach. Jeśli przechowujesz tylko jeden żeton "zapamiętaj mnie" dla każdego konta, musisz użyć tej samej wartości na obu klientach lub usunąć stary token podczas tworzenia nowego (np. Użytkownik może być zapamiętany tylko na jednej maszynie).

Proszę wyjaśnić swój pomysł na kod. Nie rozumiem wyraźnie bez kodu

Nie. Otrzymuję zapłatę za napisanie kodu; Jeśli chcesz, żebym napisał kod dla ciebie, musisz mi zapłacić. Kod zajmie znacznie więcej miejsca i czasu niż powyższy opis.

+3

+1 dla wyjaśnienia, dlaczego nie napisałeś kodu. –

+0

W tej społeczności staramy się sobie nawzajem pomagać. Jestem też deweloperem. Chciałem tylko uzyskać poradę i jakiś przykładowy kod twojego pomysłu, (Nie jestem angielskim mówcą, nie wszystkie posty są dla mnie w 100% zrozumiałe) W każdym razie, dziękuję za marnowanie czasu za darmo :) –