System logowania PHP: Remember Me (persistent cookie) [duplikat]
To pytanie ma już odpowiedź tutaj:
- "Nie wylogowuj mnie" - najlepsze podejście 12 odpowiedzi
Chciałbym dodać opcję" Zapamiętaj mnie " przed zalogowaniem.
Jaki jest najlepszy sposób bezpiecznego przechowywania plików cookie w przeglądarce użytkownika?
Na przykład Facebook ma swoje pole wyboru "Zapamiętaj mnie", dzięki czemu za każdym razem, gdy wchodzisz facebook.com jesteś już zalogowany.
Moje obecne logowanie używa prostych sesji.
2 answers
To pytanie jest często zadawane, oto kilka linków dla Ciebie.
- najlepsza praktyka wdrażania bezpiecznego "Remember Me"
- "Zapamiętaj Mnie Na Tym Komputerze" - Jak To Powinno Działać?
- "Keep Me Logged In" - najlepsze podejście
Istnieje również kilka wielkich zasobów zebranych razem w odpowiedzi na to pytanie: The Definitive Guide To website Authentication
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:23
Update (2017-08-13) : aby zrozumieć, dlaczego oddzielamy
selector
itoken
, zamiast używaćtoken
, przeczytaj Ten artykuł o dzieleniu tokenów, aby zapobiec atakom timingowym w zapytaniach SELECT.
Zamierzam wyodrębnić strategię opisaną w tym poście na blogu o bezpiecznym uwierzytelnianiu długoterminowym , ponieważ obejmuje to wiele obszarów i interesuje nas tylko część "Zapamiętaj mnie".
Preambuła - Struktura Bazy Danych
Chcemy oddzielnej tabeli od tabeli naszych użytkowników, która wygląda tak (MySQL):
CREATE TABLE `auth_tokens` (
`id` integer(11) not null UNSIGNED AUTO_INCREMENT,
`selector` char(12),
`token` char(64),
`userid` integer(11) not null UNSIGNED,
`expires` datetime,
PRIMARY KEY (`id`)
);
Najważniejsze jest to, że selector
i token
są oddzielnymi polami.
Po Zalogowaniu
Jeśli nie masz random_bytes()
, po prostu pobierz kopię random_compat.
if ($login->success && $login->rememberMe) { // However you implement it
$selector = base64_encode(random_bytes(9));
$authenticator = random_bytes(33);
setcookie(
'remember',
$selector.':'.base64_encode($authenticator),
time() + 864000,
'/',
'yourdomain.com',
true, // TLS-only
true // http-only
);
$database->exec(
"INSERT INTO auth_tokens (selector, token, userid, expires) VALUES (?, ?, ?, ?)",
[
$selector,
hash('sha256', $authenticator),
$login->userId,
date('Y-m-d\TH:i:s', time() + 864000)
]
);
}
Ponowne Uwierzytelnianie Przy Ładowaniu Strony
if (empty($_SESSION['userid']) && !empty($_COOKIE['remember'])) {
list($selector, $authenticator) = explode(':', $_COOKIE['remember']);
$row = $database->selectRow(
"SELECT * FROM auth_tokens WHERE selector = ?",
[
$selector
]
);
if (hash_equals($row['token'], hash('sha256', base64_decode($authenticator)))) {
$_SESSION['userid'] = $row['userid'];
// Then regenerate login token as above
}
}
Szczegóły
Używamy 9 bajtów losowych danych (base64 zakodowane do 12 znaków) dla naszego selektora. To zapewnia 72 bity przestrzeni kluczy i dlatego 236 bity odporności na kolizje( birthday attacks), która jest większa niż nasza pojemność pamięci (integer(11) UNSIGNED
) o współczynnik 16.
Używamy 33 bajtów (264 bity) losowości dla naszego rzeczywistego authenticatora. Powinno to być nieprzewidywalne we wszystkich praktycznych scenariuszach.
Przechowujemy hash SHA256 authenticatora w bazie danych. Zmniejsza to ryzyko podszywania się pod użytkowników po wyciekach informacji.
Obliczamy ponownie Skrót SHA256 wartości authenticator przechowywanej w pliku cookie użytkownika porównuje go z zapisanym skrótem SHA256 przy użyciu hash_equals()
aby zapobiec atakom czasowym.
Oddzieliliśmy selektor od authenticatora, ponieważ wyszukiwanie DB nie jest stałe. Eliminuje to potencjalny wpływ wycieków czasu na wyszukiwanie bez powodowania drastycznego spadku wydajności.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-13 20:30:38