Как сделать авторизацию на сайте


Пишем авторизацию пользователя на PHP — Блог веб-разработчиков

Совсем недавно я рассказывал, как при помощи PHP написать систему регистрации для своего сайта. Такой же принцип мы использовали и в своём проекте, созданию которого посвящён раздел «Сайт с нуля» на этом блоге (сам проект я покажу вам гораздо позже). Сегодня же я опишу, как написать авторизацию на сайте, используя данные, полученные от пользователя при регистрации. То есть, будет использоваться таблица MySQL, структура которой была описана в статье про регистрацию. Поэтому я настоятельно рекомендую прежде прочитать ту статью, ибо данная статья является её непосредственным продолжением. Авторизация будет работать с использованием сессий и cookie. Также в статье будет рассмотрено несколько приятных дополнений, таких, как «разлогинивание» (выход) и время последней активности пользователя. Итак, приступим…

Для начала необходимо сверстать главную страницу сайта и поместить её в корне сайта в папку template. Для данного урока нам достаточно, чтобы в этом файле была форма ввода логина и пароля, а также кнопка «Вход». Далее приведён код этой формы:

1
 2
 3
 4
 5
 
<form action="/" method="post">
 Логин: <input type="text" name="login" />
 
 Пароль: <input type="password" name="password" />
 <input type="submit" value="Войти" name="log_in" />
 
 </form>

Файл назовём index.html.

Метод передачи post необходим. Ведь мы не хотим, чтобы при авторизации логин и пароль светились в адресной строке.

Как только форма готова, создадим самый важный файл будущего сайта — главный контроллер, т. е. файл, лежащий в корне сайта — index.php. Именно он и будет запускаться при входе на сайт. На момент написания статьи на нашем проекте код этого файла занимает 92 строки, нам же понадобится пока лишь около 25 строк. Вот его код:

1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
<?
 include ('lib/connect.php'); //подключаемся к БД
 include ('lib/module_global.php'); //подключаем файл с глобальными функциями
 
  
 if($_GET['action'] == "out") out(); //если передана переменная action, «разавторизируем» пользователя
  
 if (login()) //вызываем функцию login, определяющую, авторизирован юзер или нет
 
 {
 $UID = $_SESSION['id']; //если юзер авторизирован, присвоим переменной $UID его id
 $admin = is_admin($UID); //определяем, админ ли юзер
 
 }
 else //если пользователь не авторизирован, то проверим, была ли нажата кнопка входа на сайт
 {
 if(isset($_POST['log_in'])) 
 {
 $error = enter(); //функция входа на сайт
 
 if (count($error) == 0) //если нет ошибок, авторизируем юзера
 {
 $UID = $_SESSION['id'];
 
 $admin = is_admin($UID);
 }
 }
 }
 include ('tpl/index.html'); //подключаем файл с формой
 
 ?>

Теперь более подробно разберёмся, как всё это работает.

В первых трёх строках мы просто подключаем файлы с функциями, которые будем использовать далее в коде. О них чуть позже. Далее проверим, был ли передан get-параметр action=out. Если он был передан, значит пользователь нажал на ссылку выхода с сайта. Вот, кстати, код этой ссылки. Добавьте его в файл с кодом формы для входа.

<a href="/?action=out">Выход</a>

Саму функцию, как и все остальные, рассмотрим позже. Сперва логика…

Далее идёт условие, проверяющее авторизирован ли ты (if (login())). Функция возвращает true в случае, если пользователь вошёл на сайт и false в противном случае. Если вернулось true, записываем в переменную $UID id юзера, а в переменную $admin — результат работы функции is_admin($UID). Данная функция определяет, является ли пользователь администратором и возвращает true, если юзер — админ и false в противном случае. В дальнейшем две эти переменные будут необходимы для вывода определённых элементов на странице. Так, следующим условием можно вывести форму авторизации:

1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 
<?
 If($UID) //если переменной нет, выводим форму
 {?>
 <form action="/" method="post">
 
 Логин: <input type="text" name="login" />
 Пароль: <input type="password" name="password" />
 
 <input type="submit" value="Войти" name="log_in" />
 </form>
 <?}
 ?>

Аналогично и с переменной $admin. Кстати, последний код можно включить в файл с формой.
Если же функция login() вернёт false, т. е. пользователь не вошёл на сайт, проверим, нажал ли он на кнопку входа на сайт в форме авторизации:

if(isset($_POST['log_in']))

Если да, запускаем функцию enter(), авторизирующую пользователя. Если ошибок не произойдёт и юзер успешно вошёл, создадим те же 2 переменные: $UID и $admin. В противном случае никакие переменные не создаются – пользователь является гостем. Алгоритм работы представлен на следующей схеме:

Теперь разберёмся со всеми функциями, вызываемыми в данном коде. В первую очередь опишу функцию входа на сайт:

1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 
 
function enter ()
 { 
 $error = array(); //массив для ошибок 
 if ($_POST['login'] != "" && $_POST['password'] != "") //если поля заполнены 
 
 { 
 $login = $_POST['login']; 
 $password = $_POST['password'];
 
 $rez = mysql_query("SELECT * FROM users WHERE login=$login"); //запрашиваем строку из БД с логином, введённым пользователем 
 if (mysql_num_rows($rez) == 1) //если нашлась одна строка, значит такой юзер существует в БД 
 
 { 
 $row = mysql_fetch_assoc($rez); 
 if (md5(md5($password).$row['salt']) == $row['password']) //сравниваем хэшированный пароль из БД с хэшированными паролем, введённым пользователем и солью (алгоритм хэширования описан в предыдущей статье) 
 
 { 
 //пишем логин и хэшированный пароль в cookie, также создаём переменную сессии
 setcookie ("login", $row['login'], time() + 50000); 
 setcookie ("password", md5($row['login'].$row['password']), time() + 50000); 
 $_SESSION['id'] = $row['id']; //записываем в сессию id пользователя 
 
 $id = $_SESSION['id']; 
 lastAct($id); 
 return $error; 
 } 
 else //если пароли не совпали 
 
 { 
 $error[] = "Неверный пароль"; 
 return $error; 
 } 
 } 
 else //если такого пользователя не найдено в БД 
 
 { 
 $error[] = "Неверный логин и пароль"; 
 return $error; 
 } 
 } 
  
 
 else 
 { 
 $error[] = "Поля не должны быть пустыми!"; 
 return $error; 
 } 
 
 }

Первым делом, функция проверяет, заполнил ли пользователь поля для ввода логина и пароля. Если да — продолжаем работу программы, если нет — пишем в массив $error текст ошибки и возвращаем его в основную программу, которая, узнав размерность полученного массива, не авторизирует пользователя.
Если же работа функции enter() продолжится, проверим, существует ли в БД запись с таким ником, какой ввёл юзер. Если такой записи не оказалось, вернём опять же массив с соответствующей ошибкой. Если в БД есть один пользователь с таким ником, сравним введённый пароль с паролем, хранящимся в базе данных и соответствующим нашему нику.

Сравниваем мы пароли не в чистом виде. Ведь в БД они хранятся хэшированными функцией md5(). Поэтому, прежде чем сравнивать их, необходимо тем же алгоритмом хэшировать и введённый пользователем при авторизации пароль. Если хэши совпадут, значит логин и пароль совпали и скрипт авторизирует пользователя. Если совпадения не произошло, вернём ошибку.

Теперь объясню, что же значит «авторизироваться». В данном скрипте данные об авторизации хранятся в сессии и cookie. В сессию записываем id пользователя:

И создаём два cookie: login и password с продолжительностью жизни — 50000 секунд. В первый пишем логин, а во второй — хэш пароля.

В этой строке мы выполняем функцию, отвечающую за установку времени последней активности юзера. Вот код этой функции:

1
 2
 
function lastAct($id)
 { $tm = time(); mysql_query("UPDATE users SET online='$tm', last_act='$tm' WHERE"); }

Функция перезаписывает поля online и last_act в БД. Кстати, предварительно, необходимо убедиться в существовании этих полей. Оба они имеют тип int.

Алгоритм работы функции enter() приведён на следующей иллюстрации:

Следующая функция отвечает за проверку, авторизирован ли пользователь на сайте или нет — login().

1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 
function login () { 
 ini_set ("session.use_trans_sid", true); session_start(); if (isset($_SESSION['id']))//если сесcия есть 
 
 { 
 if(isset($_COOKIE['login']) && isset($_COOKIE['password'])) //если cookie есть, то просто обновим время их жизни и вернём true { 
 SetCookie("login", "", time() - 1, '/'); SetCookie("password","", time() - 1, '/'); 
 
 setcookie ("login", $_COOKIE['login'], time() + 50000, '/'); 
 
 setcookie ("password", $_COOKIE['password'], time() + 50000, '/'); 
 
 $id = $_SESSION['id']; 
 lastAct($id); 
 return true; 
 
 } 
 else //иначе добавим cookie с логином и паролем, чтобы после перезапуска браузера сессия не слетала 
 { 
 $rez = mysql_query("SELECT * FROM users WHEREid']}'"); //запрашиваем строку с искомым id 
 
 if (mysql_num_rows($rez) == 1) //если получена одна строка { 
 $row = mysql_fetch_assoc($rez); //записываем её в ассоциативный массив 
 
 setcookie ("login", $row['login'], time()+50000, '/'); 
 
 setcookie ("password", md5($row['login'].$row['password']), time() + 50000, '/'); 
 
 $id = $_SESSION['id'];
 lastAct($id); 
 return true; 
 
 } 
 else return false; 
 } 
 } 
 else //если сессии нет, то проверим существование cookie. Если они существуют, то проверим их валидность по БД 
 { 
 if(isset($_COOKIE['login']) && isset($_COOKIE['password'])) //если куки существуют. 
 
 { 
 $rez = mysql_query("SELECT * FROM users WHERE login='{$_COOKIE['login']}'"); //запрашиваем строку с искомым логином и паролем 
 @$row = mysql_fetch_assoc($rez); 
 
 if(@mysql_num_rows($rez) == 1 && md5($row['login'].$row['password']) == $_COOKIE['password']) //если логин и пароль нашлись в БД 
 
 { 
 $_SESSION['id'] = $row['id']; //записываем в сесиию id 
 $id = $_SESSION['id']; 
 
 lastAct($id); 
 return true; 
 } 
 else //если данные из cookie не подошли, то удаляем эти куки, ибо нахуй они такие нам не нужны 
 { 
 SetCookie("login", "", time() - 360000, '/'); 
 
 SetCookie("password", "", time() - 360000, '/'); 
 return false; 
 
 } 
 } 
 else //если куки не существуют 
 { 
 return false; 
 } 
 } 
 }

Почему для авторизации мы будем использовать и COOKIE и сессию? Дело в том, что после закрытия браузера, сессия «умирает» и пользователь автоматически разлогинивается. Cookie же хранятся определённое, задаваемое нами, время. В данном случае это 50000 секунд.

Итак, разберёмся, как же эта функция работает. Её стоит запускать первой на всех страницах и модулях будущего сайта. Во-первых, она проверяет, авторизирован ли пользователь, что для дальнейшей работы скрипта крайне важно. Во-вторых, она обновляет время последней активности пользователя, а также поможет в будущем ввести систему онлайн-пользователей.

Функция вернёт true, если юзер авторизирован и false в противном случае. Пичём, в процессе её работы, будет обновлено время жизни cookie, а также они будут созданы, если не существуют.

Лучше всего работу функции online описывает эта иллюстрация:

Если есть сессия и cookie, мы обновляем время жизни cookie. Для этого мы их удаляем, устанавливая время смерти на одну секунду раньше текущего момента времени, а затем устанавливаем заново. Также функцией lastAct() обновлем время последней активности. Возвращаем true.

Если же сессия есть, а cookie по какой-то причине не оказалось, то по id пользователя получаем из БД логин и хэш пароля и пишем их в cookie. Возвращаем true.

Если нет сессии, проверим, быть может существуют cookie. Классический пример авторизации после перезапуска браузера — сессия слетела, но cookie-то живы. Тут уже сложнее, мы должны проверить, совпадает ли пара логин-пароль с какой-либо строкой из БД. Ведь юзер мог заменить в настройках для сайта cookie ручками или написать любую чушь. Если такая пара нашлась, создаём переменную сессии и возвращаем true. Если же пара не найдена, посылаем пользователя на йух и возвращаем false.

Последний, самый печальный вариант — когда ни сессии, ни cookie не оказалось… Возвращаем false.

Теперь обратим взор на функцию is_admin($UID). Она определяет, является ли юзер администратором сайта. Возможно, вам это не нужно, тогда можете опустить эту функцию и все её вызовы в контроллере. Но она может быть полезна для вывода какого либо контента на страницу, предназначенного для администраторов, а не для обычных пользователей. Функция простая и основана на ещё одном созданном столбце в БД в таблице users. Столбец называем prava. Тип int. Если юзер является обыкновенным пользователем, то присваиваем значению в этом столбце 0, если же этот юзер — админ, то присваиваем единицу. Следующая функция и определяет, что стоит в столбце prava; если единица, то возвращается true (пользователь – админ), иначе false.

1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 
function is_admin($id) { 
 @$rez = mysql_query("SELECT prava FROM users WHERE"); 
 
 if (mysql_num_rows($rez) == 1) 
 { 
 $prava = mysql_result($rez, 0); 
 
 if ($prava == 1) return true; 
 else return false; 
 
 } 
 else return false; 
 }

Ну и последняя, на самом деле очень лёгкая, функция — out(). Принцип её работы прост — удалить все «следы» пользователя – сессию и cookie.

1
 2
 3
 4
 5
 6
 7
 8
 
function out () { 
 session_start(); 
 $id = $_SESSION['id']; 
 
 mysql_query("UPDATE users SET online=0 WHERE"); //обнуляем поле online, говорящее, что пользователь вышел с сайта (пригодится в будущем) 
 unset($_SESSION['id']); //удаляем переменную сессии 
 SetCookie("login", ""); //удаляем cookie с логином 
 
 SetCookie("password", ""); //удаляем cookie с паролем 
 header('Location: http://'.$_SERVER['HTTP_HOST'].'/'); //перенаправляем на главную страницу сайта }

Код всех описанных функций помещаем в файл lib/module_global.php, который подключается в самом начале работы контроллера.

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

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

Чтобы не пропустить следующие статьи, подпишитесь на RSS.

Удачи и до следующих статей.

python - Как авторизоваться на сайте без страницы формы входа?

Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд
.

HTTP-аутентификация - веб-технология для разработчиков

HTTP обеспечивает общую основу для управления доступом и аутентификации. Эта страница представляет собой введение в структуру HTTP для аутентификации и показывает, как ограничить доступ к вашему серверу с помощью схемы HTTP «Basic».

Общая структура аутентификации HTTP

RFC 7235 определяет структуру аутентификации HTTP, которая может использоваться сервером для оспаривания запроса клиента и клиентом для предоставления информации аутентификации.

Поток запросов и ответов работает следующим образом:

  1. Сервер отвечает клиенту статусом ответа 401 (Неавторизован) и предоставляет информацию о том, как авторизоваться с помощью заголовка ответа WWW-Authenticate , содержащего как минимум один запрос.
  2. Клиент, который хочет аутентифицироваться на сервере, может сделать это, включив заголовок запроса Authorization с учетными данными.
  3. Обычно клиент представляет пользователю запрос пароля, а затем выдает запрос, включающий правильный заголовок Authorization .

В случае «базовой» аутентификации, как показано на рисунке, обмен должен происходить через соединение HTTPS (TLS) для обеспечения безопасности.

Аутентификация прокси

Тот же механизм запроса и ответа может использоваться для аутентификации прокси-сервера . Поскольку аутентификация ресурсов и аутентификация прокси могут сосуществовать, необходим другой набор заголовков и кодов состояния. В случае прокси-серверов, вызывающий код состояния - 407 (требуется аутентификация прокси), заголовок ответа Proxy-Authenticate содержит по крайней мере один запрос, применимый к прокси, а заголовок запроса Proxy-Authorization используется для предоставление учетных данных прокси-серверу.

Доступ запрещен

Если (прокси-сервер) получает действительные учетные данные, которые не подходят для доступа к данному ресурсу, сервер должен ответить кодом состояния 403 Forbidden . В отличие от 401 Unauthorized или 407 Proxy Authentication Required , аутентификация для этого пользователя невозможна.

Аутентификация изображений перекрестного происхождения

Потенциальная дыра в безопасности, недавно исправленная браузерами, - это аутентификация межсайтовых изображений.Начиная с Firefox 59 и далее ресурсы изображений, загруженные из разных источников в текущий документ, больше не могут запускать диалоги HTTP-аутентификации (ошибка 1423146), предотвращая кражу учетных данных пользователя, если злоумышленники смогли встроить произвольное изображение на стороннюю страницу.

Кодировка символов HTTP-аутентификации

Браузеры используют кодировку utf-8 для имен пользователей и паролей.

Firefox когда-то использовал ISO-8859-1 , но был изменен на utf-8 для обеспечения паритета с другими браузерами и во избежание потенциальных проблем, как описано в ошибке 1419658.

Заголовки WWW-Authenticate и Proxy-Authenticate

Заголовки ответа WWW-Authenticate и Proxy-Authenticate определяют метод аутентификации, который следует использовать для получения доступа к ресурсу. Они должны указать, какая схема аутентификации используется, чтобы клиент, желающий авторизоваться, знал, как предоставить учетные данные.

Синтаксис этих заголовков следующий:

 WWW-аутентификация: <тип> область = <область> Прокси-аутентификация:  realm =  

Здесь <тип> - это схема аутентификации («Базовая» является наиболее распространенной схемой и представлена ​​ниже).Область используется для описания защищаемой области или для обозначения объема защиты. Это может быть сообщение типа «Доступ к промежуточному сайту» или подобное, чтобы пользователь знал, к какому пространству он пытается получить доступ.

Заголовки авторизации и прокси-авторизации

Заголовки запроса Authorization и Proxy-Authorization содержат учетные данные для аутентификации пользовательского агента с (прокси) сервером. Здесь снова требуется <тип> , за которым следуют учетные данные, которые могут быть закодированы или зашифрованы в зависимости от того, какая схема аутентификации используется.

 Авторизация: <тип> <учетные данные> Прокси-авторизация: <тип> <учетные данные> 

Схемы аутентификации

Общая структура аутентификации HTTP используется в нескольких схемах аутентификации. Схемы могут различаться по уровню безопасности и доступности в клиентском или серверном программном обеспечении.

Наиболее распространенной схемой аутентификации является "Базовая" схема аутентификации, которая более подробно описана ниже. IANA ведет список схем аутентификации, но есть и другие схемы, предлагаемые хост-сервисами, например Amazon AWS.Общие схемы аутентификации включают:

Базовый
См. RFC 7617, учетные данные в кодировке base64. Более подробная информация ниже.
Держатель
См. RFC 6750, токены-носители для доступа к ресурсам, защищенным OAuth 2.0.
Дайджест
См. RFC 7616, в Firefox поддерживается только хеширование md5, см. Ошибку 472823 для поддержки шифрования SHA
HOBA
См. RFC 7486, раздел 3, H TTP O rigin- B ound A аутентификация на основе цифровой подписи
взаимное
См. RFC 8120
AWS4-HMAC-SHA256
См. Документы AWS

Базовая схема аутентификации

«Базовая» схема проверки подлинности HTTP определена в RFC 7617, которая передает учетные данные в виде пар идентификатора пользователя и пароля, закодированных с использованием base64.

Безопасность базовой аутентификации

Поскольку идентификатор пользователя и пароль передаются по сети в виде открытого текста (он закодирован в base64, но base64 является обратимым кодированием), базовая схема аутентификации не является безопасной . HTTPS / TLS следует использовать с базовой аутентификацией. Без этих дополнительных улучшений безопасности базовая проверка подлинности не должна использоваться для защиты конфиденциальной или ценной информации.

Ограничение доступа с помощью Apache и базовой аутентификации

Чтобы защитить паролем каталог на сервере Apache, вам понадобится .htaccess и файл .htpasswd .

Файл .htaccess обычно выглядит так:

 AuthType Basic AuthName "Доступ к промежуточному сайту" AuthUserFile /path/to/.htpasswd Требовать действительного пользователя 

Файл .htaccess ссылается на файл .htpasswd , в котором каждая строка состоит из имени пользователя и пароля, разделенных двоеточием (: ). Вы не можете увидеть фактические пароли, поскольку они хешируются (в данном случае с использованием хеширования на основе MD5).Обратите внимание, что вы можете назвать файл .htpasswd по-другому, если хотите, но имейте в виду, что этот файл не должен быть доступен никому. (Apache обычно настроен для предотвращения доступа к файлам .ht * ).

 aladdin: $ apr1 $ ZjTqBB3f $ IF9gdYAGlMrs2fuINjHsz. user2: $ apr1 $ O04r.y2H $ / vEkesPhVInBByJUkXitA / 

Ограничение доступа с помощью nginx и базовой аутентификации

Для nginx вам нужно будет указать местоположение, которое вы собираетесь защищать, и директиву auth_basic , которая предоставляет имя защищенной паролем области.Затем директива auth_basic_user_file указывает на файл .htpasswd , содержащий зашифрованные учетные данные пользователя, как и в приведенном выше примере Apache.

 местоположение / статус { auth_basic «Доступ к промежуточному сайту»; auth_basic_user_file /etc/apache2/.htpasswd; } 

Доступ с использованием учетных данных в URL-адресе

Многие клиенты также позволяют избежать приглашения на вход, используя закодированный URL-адрес, содержащий имя пользователя и пароль, например:

 https: // имя пользователя: пароль @ www.example.com/ 

Использование этих URL-адресов не рекомендуется . В Chrome часть username: password @ в URL-адресах даже исключена из соображений безопасности. В Firefox проверяется, действительно ли сайту требуется аутентификация, и если нет, Firefox предупредит пользователя сообщением «Вы собираетесь войти на сайт« www.example.com »с именем пользователя« username », но веб-сайт не требует аутентификации. Это может быть попыткой вас обмануть ".

См. Также

.

новейших вопросов 'authorize.net' - qaru Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
  3. Вакансии
.

новых вопросов об авторизации - Stack overflow на русском Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
  3. Вакансии Программирование и связанные с ним технические возможности карьерного роста
  4. Талант Нанимайте технических специалистов и создавайте свой бренд работодателя
  5. Реклама Обратитесь к разработчикам и технологам со всего мира
  6. О компании
.

Смотрите также

Поделиться в соц. сетях

Опубликовать в Facebook
Опубликовать в Одноклассники

Вы можете оставить комментарий, или ссылку на Ваш сайт.

Оставить комментарий