Что такое авторизация, пример авторизации

Using HTML Forms

The most important thing to notice when dealing with HTML forms and PHP is that any form element in an HTML page will automatically be available to your PHP scripts.


Try out following example by putting the source code in test.php script.

<?php
   if( $_POST || $_POST ) {
      if (preg_match("//",$_POST )) {
         die ("invalid name and name should be alpha");
      }
      
      echo "Welcome ". $_POST. "<br />";
      echo "You are ". $_POST. " years old.";
      
      exit();
   }
?>
<html>
   <body>
   
      <form action = "<?php $_PHP_SELF ?>" method = "POST">
         Name: <input type = "text" name = "name" />
         Age: <input type = "text" name = "age" />
         <input type = "submit" />
      </form>
      
   </body>
</html>

It will produce the following result −

  • The PHP default variable $_PHP_SELF is used for the PHP script name and when you click «submit» button then same PHP script will be called and will produce following result −

  • The method = «POST» is used to post user data to the server script. There are two methods of posting data to the server script which are discussed in PHP GET & POST chapter.

Шаг 1 – MySQL

Сначала нам надо создать таблицу, которая будет содержать все данные о зарегистрированных пользователях. Код запроса доступен в файле table.sql в архиве с исходниками. 

table.sql

Мы определяем  id как integer с опцией auto_increment – он будет автоматически назначаться для каждого нового зарегистрированного пользователя. Также usr определяется как unique key – в таблице не допускается существование двух записей с одинаковым именем пользователя.

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

После создания таблицы нужно заполнить переменные для соединения с вашей базой данных в файле connect.php, чтобы можно было запустить код на вашем сервере.

How this PHP user registration example works?

This example code can be separated into 3 parts.

  1. Getting user information via a HTML form.
  2. Validating user submitted information on form submit.
  3. Database handling to save registered user to the database after validation.

During registration we generally collect user information, who are ready to register with our application. Some of them will be mandatory and some of them will be optional.

So, this functionality may also include validation part to ensure about the non-emptiness and the format of the user data.  The validation could be done either in client-side or server side.

Having validation at server-side is always better. You can choose to have it in client-side also for the ease of  use of the users. But having at the server-side is not optional and a minimum requirement.

Подключение БД для регистрации:

Теперь пришло время подключить базу данных к сайту.

PHP

1 2 3 4 5 6 7 8 9 10 11 12 13 14

<?php

$server=’localhost’;// Имя или адрес сервера

$user=’root’;// Имя пользователя БД

$password=»;// Пароль пользователя

$db=’test’;// Название БД

$db=mysqli_connect($server,$user,$password,$db);// Подключение

// Проверка на подключение

if(!$db){

// Если проверку не прошло, то выводится надпись ошибки и заканчивается работа скрипта

echo»Не удается подключиться к серверу базы данных!»;

exit;

}

Если выводит, что подключение к базе данных прошло успешно, то значит всё хорошо.

Дальше подключаем этот файл в наш основной, для регистрации, для этого используем .

PHP

1 2

// Подключаем коннект к БД

require_once’db.php’;

Вот теперь всё должно хорошо работать, а если не заработает, то выведет ошибку.

Creating the Database and setting-up Tables

You can skip this step if you followed the Secure Login System Tutorial.

For this part, you will need to access your MySQL database, either using phpMyAdmin or your preferred MySQL database management application.

If you’re using phpMyAdmin follow these instructions:

  • Navigate to: http://localhost/phpmyadmin/
  • Click the Databases tab at the top
  • Under Create database, type in phplogin in the text box
  • Select utf8_general_ci as the collation
  • Click Create

You can use your own database name, but for this tutorial, I’ll use phplogin.


Click the database on the left side panel (phplogin) and execute the following SQL statement:

SQL

On phpMyAdmin this should look like:

http://localhost/phpmyadmin/

Создание API для входа пользователей

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

Откроем файл api/login.php и поместим в него следующий код

Мы сравним электронную почту пользователя и пароль из базы данных, поэтому нам нужно подключение к БД.

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

Замените комментарий // здесь будет соединение с БД в файле login.php следующим кодом:

Создание файла конфигурации (ядра)

Файл login.php не будет работать без файла core.php. Этот файл содержит общие настройки / переменные нашего приложения.

У нас есть переменные, используемые нашей библиотекой JWT для кодирования и декодирования токена. Значение $key должно быть вашим собственным и уникальным секретным ключом.

iss — адрес или имя удостоверяющего центра

aud — имя клиента для которого токен выпущен

iat — время, когда был выпущен JWT

nbf — время, начиная с которого может быть использован (не раньше, чем)

Вы также можете использовать exp — идентифицирует время истечения срока действия токена

Откроем api/config/core.php и добавим следующий код

Скачайте библиотеку PHP-JWT c GitHub’а

Скопируйте содержимое библиотеки в api/libs/

Тест входа в систему

Введём следующий URL запрос

В Body вставьте следующее значение JSON

Нам нужно сохранить сгенерированный JWT чтобы потом его использовать для проверки

Для проверки на неудачный вход в систему измените значение пароля на 222 (это неверный пароль)

fbconfig.php file overview

FacebookSession::setDefaultApplication( 'your app ID','App Secrete ' );
// login helper with redirect_uri
   $helper = new FacebookRedirectLoginHelper('You web address' );

Finally fbconfig.php file as shown below −

<?php
   
   session_start();
   
   // added in v4.0.0
   require_once 'autoload.php';
   use Facebook\FacebookSession;
   use Facebook\FacebookRedirectLoginHelper;
   use Facebook\FacebookRequest;
   use Facebook\FacebookResponse;
   use Facebook\FacebookSDKException;
   use Facebook\FacebookRequestException;
   use Facebook\FacebookAuthorizationException;
   use Facebook\GraphObject;
   use Facebook\Entities\AccessToken;
   use Facebook\HttpClients\FacebookCurlHttpClient;
   use Facebook\HttpClients\FacebookHttpable;
   
   // init app with app id and secret
   FacebookSession::setDefaultApplication( '496544657159182','e6d239655aeb3e496e52fabeaf1b1f93' );
   
   // login helper with redirect_uri
   $helper = new FacebookRedirectLoginHelper('http://www.tutorialspoint.com/' );
   
   try {
      $session = $helper->getSessionFromRedirect();
   }catch( FacebookRequestException $ex ) {
      // When Facebook returns an error
   }catch( Exception $ex ) {
      // When validation fails or other local issues
   }
   
   // see if we have a session
   if ( isset( $session ) ) {
      // graph api request for user data
      $request = new FacebookRequest( $session, 'GET', '/me' );
      $response = $request->execute();
      
      // get response
      $graphObject = $response->getGraphObject();
      $fbid = $graphObject->getProperty('id');           // To Get Facebook ID
      $fbfullname = $graphObject->getProperty('name');   // To Get Facebook full name
      $femail = $graphObject->getProperty('email');      // To Get Facebook email ID
      
      /* ---- Session Variables -----*/
      $_SESSION = $fbid;
      $_SESSION = $fbfullname;
      $_SESSION =  $femail;
      
      /* ---- header location after session ----*/
      header("Location: index.php");
   }else {
      $loginUrl = $helper->getLoginUrl();
      header("Location: ".$loginUrl);
   }
?>

Identifying Browser & Platform

PHP creates some useful environment variables that can be seen in the phpinfo.php page that was used to setup the PHP environment.


One of the environment variables set by PHP is HTTP_USER_AGENT which identifies the user’s browser and operating system.

PHP provides a function getenv() to access the value of all the environment variables. The information contained in the HTTP_USER_AGENT environment variable can be used to create dynamic content appropriate to the browser.

Following example demonstrates how you can identify a client browser and operating system.

NOTE − The function preg_match()is discussed in PHP Regular expression session.

<html>
   <body>
   
      <?php
         function getBrowser() { 
            $u_agent = $_SERVER; 
            $bname = 'Unknown';
            $platform = 'Unknown';
            $version = "";
            
            //First get the platform?
            if (preg_match('/linux/i', $u_agent)) {
               $platform = 'linux';
            }elseif (preg_match('/macintosh|mac os x/i', $u_agent)) {
               $platform = 'mac';
            }elseif (preg_match('/windows|win32/i', $u_agent)) {
               $platform = 'windows';
            }
            
            // Next get the name of the useragent yes seperately and for good reason
            if(preg_match('/MSIE/i',$u_agent) && !preg_match('/Opera/i',$u_agent)) {
               $bname = 'Internet Explorer';
               $ub = "MSIE";
            } elseif(preg_match('/Firefox/i',$u_agent)) {
               $bname = 'Mozilla Firefox';
               $ub = "Firefox";
            } elseif(preg_match('/Chrome/i',$u_agent)) {
               $bname = 'Google Chrome';
               $ub = "Chrome";
            }elseif(preg_match('/Safari/i',$u_agent)) {
               $bname = 'Apple Safari';
               $ub = "Safari";
            }elseif(preg_match('/Opera/i',$u_agent)) {
               $bname = 'Opera';
               $ub = "Opera";
            }elseif(preg_match('/Netscape/i',$u_agent)) {
               $bname = 'Netscape';
               $ub = "Netscape";
            }
            
            // finally get the correct version number
            $known = array('Version', $ub, 'other');
            $pattern = '#(?<browser>' . join('|', $known) . ')+(?<version>*)#';
            
            if (!preg_match_all($pattern, $u_agent, $matches)) {
               // we have no matching number just continue
            }
            
            // see how many we have
            $i = count($matches);
            
            if ($i != 1) {
               //we will have two since we are not using 'other' argument yet
               
               //see if version is before or after the name
               if (strripos($u_agent,"Version") < strripos($u_agent,$ub)){
                  $version= $matches;
               }else {
                  $version= $matches;
               }
            }else {
               $version= $matches;
            }
            
            // check if we have a number
            if ($version == null || $version == "") {$version = "?";}
            return array(
               'userAgent' => $u_agent,
               'name'      => $bname,
               'version'   => $version,
               'platform'  => $platform,
               'pattern'   => $pattern
            );
         }
         
         // now try it
         $ua = getBrowser();
         $yourbrowser = "Your browser: " . $ua . " " . $ua .
            " on " .$ua . " reports: <br >" . $ua;
         
         print_r($yourbrowser);
      ?>
   
   </body>
</html>

This is producing following result on my machine. This result may be different for your computer depending on what you are using.

It will produce the following result −

Your browser: Google Chrome 54.0.2840.99 on windows reports: 
Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) 
   Chrome/54.0.2840.99 Safari/537.36

Создаём регистрацию на PHP:

Для этого пишем скрипт который будет ниже:

PHP

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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

// Проверяем нажата ли кнопка отправки формы

if(isset($_REQUEST’doGo’)){

// Все последующие проверки, проверяют форму и выводят ошибку

// Проверка на совпадение паролей

if($_REQUEST’pass’!==$_REQUEST’pass_rep’){

$error=’Пароль не совпадает’;

}

// Проверка есть ли вообще повторный пароль

if(!$_REQUEST’pass_rep’){

$error=’Введите повторный пароль’;

}

// Проверка есть ли пароль

if(!$_REQUEST’pass’){

$error=’Введите пароль’;

}

// Проверка есть ли email

if(!$_REQUEST’email’){

$error=’Введите email’;

}

// Проверка есть ли логин

if(!$_REQUEST’login’){

$error=’Введите login’;

}

// Если ошибок нет, то происходит регистрация

if(!$error){

$login=$_REQUEST’login’;

$email=$_REQUEST’email’;

// Пароль хешируется

$pass=password_hash($_REQUEST’pass’,PASSWORD_DEFAULT);

// Если день рождения не был указан, то будет самый последний год из доступных

$DOB=$_REQUEST’year_of_birth’;

// Добавление пользователя

mysqli_query($db,»INSERT INTO `users` (`login`, `email`, `password`, `DOB`) VALUES (‘».$login.»‘,'».$email.»‘,'».$pass.»‘, ‘».$DOB.»‘)»);

// Подтверждение что всё хорошо

echo’Регистрация прошла успешна’;

}else{

// Если ошибка есть, то выводить её

echo$error;

}

}

?>

<!DOCTYPE html>

<html lang=»ru»>

<head>

<meta charset=»UTF-8″>

<meta name=»viewport»content=»width=device-width, initial-scale=1.0″>

<meta http-equiv=»X-UA-Compatible»content=»ie=edge»>

<title>Зарегистрироваться<title>

<head>

<body>

<form action=»<?= $_SERVER ?>»>

<p>Логин<input type=»text»name=»login»id=»»><samp style=»color:red»>*<samp><p>

<p>EMail<input type=»email»name=»email»id=»»><samp style=»color:red»>*<samp><p>

<p>Пароль<input type=»password»name=»pass»id=»»><samp style=»color:red»>*<samp><p>

<p>Повторитепароль<input type=»password»name=»pass_rep»id=»»><samp style=»color:red»>*<samp><p>

<?php$year=date(‘Y’);?>

Годрождения

<select name=»year_of_birth»id=»»>

<option value=»»>—-<option>

<?phpfor($i=$year-14;$i>$year-14-100;$i—){?>

<option value=»<?= $i ?>»><?=$i?><option>

<?php}?>

<select>

<p><input type=»submit»value=»Зарегистрироваться»name=»doGo»><p>

<form>

<body>

<html>

HTML я не стал рассказывать, так как, там всё понятно, да и вообще программист должен разберется в коде.

Работа с формами через Ajax

Для обработки Ajax-запросов создадим класс AjaxRequest. Сохраним его в файле.

Этот класс облегчит нам обработку данных, отправленных пользователем из формы. В качестве конструктора, он принимает массив с данными запроса ( или ).

В запросе обязательно должно быть поле , которое определяет текущее действие. Например, при регистрации значением  будет «register», а при авторизации — «login».

Метод  нужен для получения параметра из запроса. Он делает дополнительную проверку на существование ключа массива и возвращает , если запрос не содержит нужных данных.

Функция  используется для формирования ответа. Метод  нужен для передачи сообщения об ошибке в поле формы.

Для того, чтобы вернуть ответ пользователю, мы используем метод . Он генерирует строку в JSON-формате, задает нужные HTTP-заголовки и возвращает данные клиенту.

В файле  происходит непосредственная обработка запросов через класс .


Содержимое ajax.php:

Формат JSON-ответа

На клиентской стороне, мы должны иметь возможность показать результат операции в понятном для человека виде. Для этого мы возвращаем JSON ответ в таком формате:

Обработка ответов происходит в методах объекта . Пример обработчика ответа для авторизации на сайте:

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

Регистрация на сайте

Перед тем, как мы начнем добавлять аутентификацию на своем сайте, придётся добавить форму для регистрации нового аккаунта.Аккаунт — это учётная запись пользователя. Чтобы завести аккаунт, требуется пройти регистрацию — это заполнение специальной формы, где пользователь указывает свою почту, пароль, и, возможно, дополнительную информацию. После регистрации все данные из формы сохраняются в базе данных как есть

Но хранению паролей нужно уделить особое внимание

Хранение паролей

Пароль пользователя — это секретный набор символов, который используется в дальнейшем в ходе аутентификации. Зная пароль пользователя, злоумышленник может войти на сайт под его именем. По этой причине пароль нельзя хранить в базе в открытом виде. Ведь если информацию из БД сайта украдут, то данные всех пользователей станут скомпрометированными. Вместо самого пароля, в базе будут храниться их отпечатки — хэши.

Что такое хеширование

Отпечаток (хэш) — это результат работы функции хэширования, которая вернёт для любого значения строку фиксированной длины. Используя специальный математический алгоритм, такая функция умеет преобразовывать любую переданную информацию к строке фиксированной длины (например, 32 или 64 символа). Причём любому массиву информации, будь это все статьи из Википедии, или одно слово, всегда будет соответствовать уникальный отпечаток. Повторный вызов функции для одного и того же исходника всегда возвращает один и тот же хэш. Обратная операция (получить из отпечатка оригинал) невозможна.

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

«Я знаю только то, что ничего не знаю, но другие не знают и этого»

Результат обработки этой строки хэширующей функцией SHA-1 будет таким:

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

Реализация регистрации пользователя

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

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

getById()

Теперь перейдем к методам, реализующим доступ к базе данных MySQL. Первый из них — . Он принимает в качестве аргумента ID статьи  () и возвращает запись с указанным ID из таблицы , сохраняя данные в новом объекте .

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

Для разрешения вызова метода без объекта  мы добавляем декларацию к определению метода. Таким образом разрешается вызов метода непосредственно без определения объекта.

public static function getById( $id ) {

Метод использует PDO для соединения с базой данных, получает запись статьи с помощью запроса SQL и сохраняет данные в новом объекте , который возвращается в вызывающий код. PDO — PHP Data Objects —объектно-ориентированная библиотека, встроенная в PHP, которая облегчает связь скриптов PHP с базами данных.

Разберем метод подробнее:

  1. Соединение с базой данных

    $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
    

    Здесь выполняется соединение с базой данных MySQL с помощью данных из файла . Дескриптор соединения сохраняется в переменной . Данный дескриптор используется в остальном коде для обмена данных с базой.

  2. Получаем запись статьи

    $sql = "SELECT *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles WHERE id = :id";
    $st = $conn->prepare( $sql );
    $st->bindValue( ":id", $id, PDO::PARAM_INT );
    $st->execute();
    $row = $st->fetch();
    

    Выражение возвращает все поля () из записи в таблице , которые соответствуют заданному полю . Значение поля возвращается в формате времени UNIX, вместо формата для дат MySQL, что упрощает процесс сохранения в нашем объекте.

    Вместо того, чтобы помещать наш параметр непосредственно в строку , что увеличивает риск нарушения системы безопасности, мы используем . Такой параметр известен как placeholder (указатель места размещения). Далее мы вызываем метод PDO для привязывания значение к указателю места размещения.

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

    Подготовка выражения используется для работы со многими базами данных. Она позволяет выполнять запросы быстрее и безопаснее.

    Затем мы привязываем значение переменной ( ID нужной статьи) к указателю места размещения с помощью вызова метода .

    И вызываем метод для выполнения запроса. После чего используем метод для перемещения полученной записи в ассоциированный массив с именами полей и соответствующими значениями, который хранится в переменной .

  3. Закрываем соединение

    $conn = null;
    

    Так как нам больше не нужно соединение, мы закрываем его, присваивая значение переменной . Закрывать соединение с базой данных как можно быстрее является хорошей практикой для освобождения памяти на сервере.

  4. Возвращаем объект

    if ( $row ) return new Article( $row );
    }
    

    Последним действием в нашем методе является создание объекта  , который будет содержать запись из базы данных, и возвращение его вызывающему коду. Сначала проверяем наличие данных в переменной после вызова метода . Если данные есть, создаем новый объект передавая переменную ему . Будет вызван конструктор класса, который наполнит объект данными из массива . Затем возвращаем готовый объект и работа метода завершена.

Сессии

Мы уже умеем сохранять информацию для пользователя между посещениями страницы с помощью кук. Но зачем же нам ещё сессии, и для чего они нужны? Сессии, они же сеансы, это, по сути, просто удобная обёртка над куками. Они также позволяют хранить данные, релевантные пользователю, но с некоторыми отличиями и ограничениями:

  • Данные хранятся не произвольное время, а только до закрытия вкладки с веб-страницей.
  • Чтобы сессии работали, в начале каждого сценария надо вызывать функцию .
  • Доступный объём для хранения информации намного больше.

Запись и чтение информации при использовании сессий выглядит просто как работа со специальным массивом .

Как устроены сессии

  1. PHP генерирует уникальный идентификатор браузера.
  2. Идентификатор сохраняется в специальную куку и передаётся с каждым запросом.
  3. Все данные, которые записываются в сессию, PHP автоматически сохраняет в специальном файле на сервере.

Благодаря существованию сессий в PHP, мы можем сохранять любые данные так же просто, как присваивать их переменным. Но, в отличие от переменных, эти данные будут сохраняться для пользователя между запросами в пределах сеанса.

Перепишем сценарий для подсчета посещений, но теперь используем сессии:


С этим читают