ОБЗОР

  • Что такое аутентификация?
  • Аутентификация против авторизации
  • Почему аутентификация?
  • Реализация аутентификации в приложении node js

Что такое аутентификация

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

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

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

Почему аутентификация

Аутентификация пользователя имеет решающее значение для защиты конфиденциальной информации.

Реализация аутентификации в приложении node js

В рамках аутентификации, которая включает передачу идентификатора и пароля между клиентом и сервером, необходимо использовать зашифрованную связь путем реализации протокола HTTPS.
Создание HTTPS-сервера с помощью Node.js очень похоже на создание HTTP-сервера. Разница заключается в добавлении при создании сервера информации, необходимой для шифрования связи. Используемые сертификаты должны быть указаны.
Сертификаты должны быть получены от центра сертификации, который считается надежным. Let’s Encrypt — это центр сертификации, который позволяет получить сертификат бесплатно. Также можно «самоподписывать» свои собственные сертификаты (но использование этих сертификатов затем вызывает предупреждение системы безопасности в браузерах).
Поэтому для создания HTTPS-сервера необходимо указать закрытый ключ и соответствующий сертификат для сервера. Остальное не меняется по сравнению с HTTP-версией. Действуйте, как показано в коде ниже. Можно отметить, что необходимо использовать синхронное чтение файлов сертификатов, так как невозможно создать сервер и, следовательно, выполнить строки, следующие за чтением, до окончания чтения этих файлов.

// fichier ./secured-server.js
const https = require('https');
const fs = require('fs';

// chargement des certificats
const privateKey  = fs.readFileSync('./certs/certificat.key', 'utf8');
const certificate = fs.readFileSync('./certs/certificat.crt', 'utf8');

// création du serveur HTTPS
const credentials = {
                      key : privateKey,
                      cert : certificate
                    };
const securedHttpsServer = https.createServer(
  credentials,
  (request, response) => {
    // création et envoi de la réponse
    response.writeHead(200, {"Content-Type": "text/html"});
    response.write('<h1>HTTPS secured server</h1>');
      response.end();
  }
);

securedHttpsServer.listen(8081);


Войти в полноэкранный режим

Выйти из полноэкранного режима

Внимание, для доступа к HTTPS-серверу в браузере необходимо явно указать используемый протокол и, следовательно, указать https://локальный:8081. Во время первого доступа необходимо будет переопределить предупреждение системы безопасности, указывающее, что сертификат не распознан, поскольку он самоподписанный.

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

Базовая аутентификация упрощает настройку контроля доступа на основе имени пользователя и пароля. Этот механизм, пожалуй, самый простой в своем роде. Базовая аутентификация не использует файлы cookie или механизм сеанса. Информация об аутентификации передается в заголовке HTTP в поле вида «Авторизация: основные учетные данные». «credentials» содержит строку, полученную путем объединения имени пользователя и пароля, разделенных «:». Эта строка просто закодирована в Base64. Таким образом, эти данные не зашифрованы, поэтому необходимо использовать базовую аутентификацию в сочетании с HTTPS. Эта информация не отправляется с каждым запросом и поэтому кэшируется браузером (пока он не будет закрыт).
Предоставленный код содержит простой сервер, созданный с помощью Express. Только для иллюстративных целей.

Нам придется использовать pug в качестве шаблонизатора.
Чтобы получить больше информации

// fichier ./routes/index.js
const express = require('express');
const router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;
Войти в полноэкранный режим

Выйти из полноэкранного режима

//fichier ./routes/protect.js
const express = require('express');
const router = express.Router();


/* GET protect page. */
router.get('/', function(req, res, next) {
  res.render('protect', { title: 'Express' });
});

module.exports = router;
Войти в полноэкранный режим

Выйти из полноэкранного режима

Маршрутизатор управляет двумя путями: » и «/protect». Мы хотим, чтобы первый был свободно доступен, а второй защищен базовой аутентификацией.

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

Промежуточное ПО определяется в папке ./middleware/authentication.js. Как было сказано ранее, базовая аутентификация основана на информации, размещенной в свойстве «авторизация» заголовка запроса. Поэтому мы должны начать с получения значения этого свойства:

// fichier ./middleware/authentifcation.js
const authentication = (req, res, next) => {
  const authheader = req.headers.authorization;
  (...)
Войти в полноэкранный режим

Выйти из полноэкранного режима

Затем необходимо рассмотреть две ситуации в зависимости от наличия или отсутствия этого свойства. Если он отсутствует, в ответ должен быть отправлен запрос аутентификации с указанием заголовка WWW-Authenticate. Этот ответ отправляется со статусом 401, что соответствует отказу в доступе («несанкционированный доступ»).

// fichier ./middleware/authentifcation.js
const authentication = (req, res, next) => {
  (...)
  if (!authheader) {
    res.setHeader('WWW-Authenticate', 'Basic realm="mon site à moi", charset="UTF-8"');
    res.status(401).end();
  }
  (...)
Войти в полноэкранный режим

Выйти из полноэкранного режима

После этого ответа браузер запрашивает у пользователя аутентификацию, отображая специальное приватное окно. Информация, предоставленная пользователем, используется для подачи неверного заголовка «аутентификация».
Если свойство аутентификации присутствует в заголовке, необходимо проверить правильность содержащейся в нем информации. Для этого необходимо извлечь часть учетных данных свойства «авторизация», удалив базовую часть, расположенную в начале, декодировать Base64 и отделить имя пользователя от пароля (через:). Затем мы можем сверить эту информацию с ожидаемыми значениями (в нашем случае эти значения определены в ./config/secret.js). Если они совместимы, доступ разрешается путем «пропуска» запроса, который передается следующему промежуточному программному обеспечению с помощью вызова next. В противном случае отправляется новый запрос на аутентификацию, после чего мы действуем точно так же, как и раньше.

// fichier ./middleware/authentication.js
const secret = require ('../config/secret.js');

const authentication = (req, res, next) => {
  (...)
  else {
    /*extraire la partie credentials de la propriété "authorization", en en supprimant la partie Basic située au début, décoder le Base64 */
    const credentials = new Buffer.from(authheader.split(' ')[1],'base64').toString();
    const [user,password] = credentials.split(':');
    if (user === secret.user && password === secret.password) {
        // let's continue
        next()
    } else {
      // mauvais user name ou password
      res.setHeader('WWW-Authenticate', 'Basic realm="mon site à moi", charset="UTF-8"');
      res.status(401).end();
    }
  }
Войти в полноэкранный режим

Выйти из полноэкранного режима

Таким образом, вот полный код этого промежуточного программного обеспечения:

// fichier ./middleware/authentifcation.js
const secret =require('../config/secret.js');

const authentification = (req, res, next) => {
    const authheader = req.headers.authorization;
    if (!authheader) {
        res.setHeader('WWW-Authenticate', 'Basic realm="mon site à moi", charset="UTF-8"');
        res.status(401).end();
    }
    else {
      /*extraire la partie credentials de la propriété "authorization", en en supprimant la partie Basic située au début, décoder le Base64 */
      const credentials  = new Buffer.from(authheader.split(' ')[1],'base64').toString();
      const [user,password] = credentials.split(':');
      if (user === secret.user && password === secret.password) {
          // let's continue
          next();
      } else {
        // mauvais user name ou password
        res.setHeader('WWW-Authenticate', 'Basic realm="mon site à moi", charset="UTF-8"');
        res.status(401).end();
      }
    }
}

module.exports = authentification;
Войти в полноэкранный режим

Выйти из полноэкранного режима

В этом примере для простоты имя пользователя и пароль задаются уникальным образом в файле /config/secret.js. Можно считать, что при каждой попытке аутентификации в скрипте /middleware/authentifcation.js функция аутентификации проверяет, соответствует ли полученная пара (логин, пароль) пользователю, зарегистрированному в базе данных.

Использование ПО промежуточного слоя аутентификации

Теперь должно быть установлено промежуточное ПО аутентификации. Возможны две ситуации: либо вы хотите защитить весь сайт, либо необходимо защитить только определенные страницы.

В первом случае промежуточное ПО должно быть установлено глобально. Этого можно добиться на уровне файла ./app.js, поместив это промежуточное ПО перед всеми остальными, что обеспечивает контроль доступа перед любой дальнейшей обработкой запроса. Как мы видели в определении нашего промежуточного ПО, только успешная аутентификация позволяет получить доступ к другим промежуточным ПО, установленным позже, благодаря вызову next.

// fichier ./app.js
(...)
const app = express();

const authentification = require('./middlewares/authentifcation.js');
app.use(authentication);
(...)
Войти в полноэкранный режим

Выйти из полноэкранного режима

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

Мы применяем его здесь, на уровне маршрутизатора ./routes/index.js, чтобы реализовать контроль доступа только на путях «/protect». Этим маршрутам достаточно указать перед функцией-контроллером, которая управляет их логикой (для удобства это та же самая функция), что необходимо использовать промежуточное ПО аутентификации:

// fichier ./app.js
const express = require("express");
const indexRouter = require("./routes/index");
const protectRouter = require("./routes/protect");
const authentification = require("./middleware/authentifcation.js");
var app = express();

// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");

app.use("/", indexRouter);
app.use("/protect",authentification, protectRouter);
app.listen(9000,()=>{
  console.log("active au port 9000");
})
module.exports = app;

Войти в полноэкранный режим

Выйти из полноэкранного режима

Затем мы можем проверить, что у нас есть доступ без контроля к URL но что вы должны аутентифицироваться для (защищать).

Чтобы не закрывать браузер, если вы запустили сервер с помощью nodemon, просто измените информацию аутентификации в ./config/secret.js, чтобы снова запустить процесс аутентификации.