Концепция и логика системы входа?

Я хочу знать процесс, которому обычно следуют веб-приложения для поддержания входа в систему между несколькими запросами, а также то, как они управляют вещами с помощью COOKIES.

В моей форме входа я предоставляю функцию «Запомнить меня».

Когда пользователь входит в систему, я проверяю действительность имени пользователя и пароля из базы данных. Если это действительно так, я проверяю, выбрано ли «Запомнить меня», если да, то сохраняю имя пользователя и пароль в сеансе в зашифрованном формате. И, наконец, сохранение имени пользователя и пароля в SESSION.

Когда пользователь переходит с одной страницы на другую, сначала я запускаю сценарий проверки входа, который проверяет, есть ли какое-либо значение в файлах cookie, а затем проверяет это имя пользователя и пароль из базы данных, чтобы проверить их действительность. Если в cookie нет значения, а в сеансе есть какое-то значение, то я извлекаю значение сеанса и не проверяю его из базы данных.

Я не проверяю форму значения сеанса db, чтобы не нажимать db без необходимости, ускорьте работу. В случае файлов cookie они могут быть изменены, поэтому необходима проверка.

Это то, что моя концепция, это правильно? Это правильный путь, и обычно веб-сайты похожи на SO, и другие работают с таким методом?

Или веб-сайты проверяют подлинность входа при каждой загрузке страницы, независимо от того, в сеансе или в файлах cookie?

Пожалуйста, проверьте и дайте свои мысли и концепции для этого сценария.

Спасибо!


person Prashant    schedule 23.02.2011    source источник
comment
Возможно полезно: Членство пользователя с PHP   -  person drudge    schedule 23.02.2011
comment
@Prashant: Пожалуйста, напишите мне по адресу [email protected], нужно обсудить в частном порядке. Также, пожалуйста, удалите это после прочтения.   -  person Shantanu Gupta    schedule 04.03.2012


Ответы (1)


Во-первых, просто отследите, вошел ли кто-то в систему. После этого мы позаботимся о функции «запомнить меня».

Чтобы узнать, вошел ли кто-то в систему, просто посмотрите на массив $_SESSION. Все, что там есть, потому что вы положили это туда раньше. Итак, при обработке формы входа, если имя пользователя и пароль верны, вы сохраняете имя пользователя, идентификатор пользователя или что-то еще в сеансе ($_SESSION['username'] = $username;).

Всякий раз, когда пользователь загружает любую страницу, вы просто проверяете

if (isset($_SESSION['username'])) {
    // $_SESSION['username'] is logged in
} else {
    // nobody is logged in
}

Нет необходимости хранить пароль в $_SESSION (на самом деле в целях безопасности его лучше нигде не хранить, кроме хеширования в базе данных).

Теперь функция «запомнить меня»… Сначала несколько соображений:

  • Любой пользователь может изменить файлы cookie своего браузера, поэтому вы должны быть уверены, что файл cookie, отправленный в приложение, не был изменен.
  • Пользователи могут проверить это на общедоступных компьютерах (в библиотеках и т. д.), поэтому вам нужна система, которая сделает это недействительным.
  • Если пользователь выходит из вашего приложения, запоминающий его файл cookie должен быть стерт.

Во-первых, представьте, что в файле cookie вы храните имя пользователя, которого нужно «запомнить» (ОЧЕНЬ НЕБЕЗОПАСНО!!). Это означает, что если какой-либо пользователь создаст файл cookie для вашего веб-приложения с содержимым «joe», ваше приложение будет думать, что пользователь joe запомнен на этом компьютере, поэтому предоставьте доступ этому злоумышленнику, как если бы он / она был joe. Итак, нам нужно каким-то образом зашифровать/хешировать cookie.

Что касается второго пункта, аннулирования «запомнить меня» на некоторых компьютерах, мы каким-то образом будем использовать пароль. Если какой-то пользователь хочет сделать недействительными все компьютеры, на которых он/она мог установить флажок «запомнить меня», все, что ему/ей нужно сделать, это изменить свой пароль. Это также означает, что если он/она изменит свой пароль, все сохраненные логины для его/ее учетной записи будут аннулированы по той же самой причине. Но лучше перестраховаться, чем потом сожалеть...

Итак, когда вы обрабатываете логин и имя пользователя и пароль верны, и опция «запомнить меня» отмечена, в дополнение к сохранению имени пользователя в сеансе вы сохраняете хэш имени пользователя и пароля (и немного соли, если вы будет) в файле cookie, который вы отправляете пользователю. Также вам необходимо сохранить в файле cookie имя пользователя в виде простого текста (или зашифрованного обратимым способом), чтобы узнать, какой пользователь пытается «войти в систему» ​​через файл cookie, и проверить хэш имени пользователя и пароля в файле cookie с помощью хэша логин и пароль в базе. Если эта проверка верна, вы затем сохраняете имя пользователя в сеансе и больше не проверяете файл cookie этого пользователя (по крайней мере, для этого сеанса).

Итак, в целом ваш код может выглядеть так:

логин.php

if (check_login($_POST['username'], $_POST['password'])) {
    // login correct
    $_SESSION['username'] = $_POST['username'];
    if (isset($_POST['remember_me'])) {
        // we hash the password because we **NEVER** store it in plain text anywhere
        // so when we would like to check if the cookie value is correct, we will not
        // be able to do so if the hash in the cookie was done from the plaintext
        // password.
        $value = sprintf('%s:%s', $_POST['username'], md5($_POST['username'].hash_password($_POST['password'])));
        setcookie('rememberme', $value);
    }
    redirect('/your/home/page.php'); // view Post/Redirect/Get design pattern
} else {
    // login incorrect, show error message and whatever...
}

в начале каждого php-файла (или лучше во включенном файле для начальной загрузки вашего приложения)

if (isset($_SESSION['username'])) {
    // $_SESSION['username'] is logged in, proceed as you wish
} else if (isset($_COOKIE['rememberme'])) {
    // this user has checked the remember me feature some time ago in a previous login.
    // let's check if it is valid.
    list($username, $hash) = explode(':', $_COOKIE['rememberme']);

    // we need to get the password hash stored for this user (remember you **NEVER** store passwords in plain text
    $pwd_hash = obtain_password_hash_from_username($username);
    if ($hash == sprintf('%s:%s', $username, md5($username.$pwd_hash))) {
        // yeah, the user remembered is correct. We'll save it to the session to not do this shit again
        $_SESSION['username'] = $username;
    } else {
        // the cookie value is not correct so maybe an attacker is trying to fool us,
        // or the user changed his password. Whatever it is, we remove the cookie
        // because it's no longer valid
        setcookie('rememberme', '', time() - 3600);
    }

} else {
    // this user is neither logged in nor "remembered"
}

Способ хеширования пароля пользователя зависит от вас. Вам может понравиться простой md5 или ша, соленый md5 или ша (лучше) или какой-нибудь трудоемкий метод, такой как иглобрюх (рекомендуется). Для хеширования куки я использовал простой md5, но вы можете выбрать любой из методов, описанных ранее.

Я думаю, это все.

person Carlos Campderrós    schedule 23.02.2011
comment
Это совершенно правильно. Но как насчет перехвата сеанса или чего-то подобного, что может скомпрометировать сеанс? и действительно ли сессии так легко могут быть скомпрометированы? - person Prashant; 23.02.2011
comment
Для перехвата сеанса злоумышленнику необходим доступ к файлу cookie сеанса. Это возможно, если злоумышленник находится где-то на сетевом маршруте между клиентом и сервером (человек посередине) или в той же некоммутируемой сети, что и клиент, или в той же открытой сети Wi-Fi. В этом случае злоумышленник может перехватить трафик, прочитать файл cookie сеанса законного пользователя и перехватить его сеанс. Единственная защита от этого — сквозное шифрование (SSL). - person Carlos Campderrós; 23.02.2011
comment
Другие способы получения злоумышленником файла cookie сеанса законного пользователя — это атака XSS. Чтобы избежать такого рода атак, вы должны вывести свой вывод на html-страницу (та же концепция, что и экранирование значений перед запросом к базе данных, чтобы избежать sql-инъекций). Через XSS злоумышленник может внедрить в ваше приложение некоторый javascript, и этот javascript может попытаться получить доступ к файлу cookie сеанса законного пользователя. Чтобы предотвратить доступ JavaScript к вашим файлам cookie, используйте флаг http_only в setcookie(...) и session_set_cookie_params(...). - person Carlos Campderrós; 23.02.2011
comment
Спасибо, Карлос, ваш ответ наверняка поможет мне правильно разработать систему входа в систему для моего приложения :) - person Prashant; 24.02.2011
comment
НИКОГДА не храните хешированные пароли в куках! Очень легко получить настоящий пароль, когда у злоумышленника есть хэш. Современные системы входа в систему сохраняют только временный (!) хэш случайной строки, сгенерированной именно для этого пользователя. - person Sliq; 20.08.2013