@particle_accelerator

Http аутентификация работает неправильно, почему?

Хочу сделать вход на сайт с паролем для пользователей, имеющих username и password в базе данных. Для этого есть код:

<?php
            require_once('shared_php/connect_vars.php');
            require_once('shared_php/app_vars.php');
            
            header('HTTP/1.1 401 Unauthorized');
            header('WWW-Authenticate:Basic realm="entering"');
            exit ("<h3>Неверное имя пользователя или пароль. Попробуйте еще раз.</h3>");
            // Если была нажата "Отмена"
        
            $username=mysqli_real_escape_string($connect, trim($_SERVER['PHP_AUTH_USER']));
            $password=mysqli_real_escape_string($connect, trim($_SERVER['PHP_AUTH_PW']));
            $connect=mysqli_connect(DM_HOST, DB_USER, DB_PASSWORD, DB_NAME);
            //Проверка логина и пароля
            $check_password="SELECT user_id, username FROM signups WHERE username='$username' AND password=SHA('$password')"; //Выберутся все такие username; В идеале - одна строка
            //с логином, паролем и другой инфой (ненужной) в ней
            $query=mysqli_query($connect, $check_password);
            
            if (mysqli_num_rows($query)==1) {
                //все норм
                $row=mysqli_fetch_array($query);
                $user_id=$row['user_id'];
                $username=$row['username'];
            }


Однако когда ввожу правильные логин и пароль, которые точно есть в базе, выполняется блок else (снова появляется форма ввода логина и пароля).

Кроме того, если просто отдельно поставить на какую-нибудь страницу что-то вроде этого:

<?php
    $username='pet';
    $password='rocks';
    if  (($_SERVER['PHP_AUTH_USER']!=$username) OR ($_SERVER['PHP_AUTH_PW']!=$password)) {
        // Что-то не так
        header('HTTP/1.1 401 Unauthorized');
        header('WWW-Authenticate:Basic realm="petrocks"');
        
        exit ("<h3>Неверное имя пользователя или пароль. Попробуйте еще раз.</h3>");
    // Если была нажата "Отмена"
    }
?>


То первый раз заходит нормально (при вводе верных данных), но если после этого сменить в скрипте логин/пароль то после обновления страницы и ввода новых верных данных - возникает ошибка (снова перезагружает форму), и так до тех пор, пока в скрипте не вернуть старые логин и пароль и не ввести их затем в форму (после этого грузит нужную страницу).
  • Вопрос задан
  • 1698 просмотров
Пригласить эксперта
Ответы на вопрос 2
Я думаю, что проблема в том, что в первом случае вы каждый раз посылаете 401 статус, независимо от того, ввёл ли уже пользователь правильные данные или нет. Попробуйте обернуть это во что-то вроде:

$authenticated = false;
if (isset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
  // ищем пользователя в базе
  // выставляем $authenticated в true/false в зависимости от того, нашёлся ли пользователь.
}

if ($authenticated) {
  // показываем страницу аутентифицированному пользователю
} else {
  header('HTTP/1.1 401 Unauthorized');
  header('WWW-Authenticate:Basic realm="petrocks"');

  echo 'Представься, мразь', PHP_EOL;
}
Ответ написан
Комментировать
Stac
@Stac
В дополнение к ответу ozgg:

1) Не забудьте, что при такой авторизации реализовать logout (выход из системы), а то скоро придется писать второй вопрос тут :)

Т.к. нет простого способа заставить браузер перестать слать вам логин и пароль при каждом запросе, то факт логаута нужно реализовывать своими силами.

И учитывать это при логине. Т.е. нужно дополнить условие для поиска пользователя в БД - не только проверять наличие $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'], но и проверить вашу переменную хранящую признак, что пользователь разлогинен

2) Осторожнее с trim. Если у вас запрещены пробелы в логине и пароле, почему они удаляются только с концов?

3) Если была нажата кнопка "Отмена" лучше делать редирект на какую-то релевантную страницу (главную например). Это из опыта общения с Клиентами.

4) Вместо заголовка "HTTP/1.1 401 Unauthorized" лучше использовать "Status: 401 Unauthorized". Тоже из опыта. Опыта развертывания на Windows-сервер.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы