Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Code
  2. Node.js
Code

Автентифікація Node-застосунків за допомогою Passport

by
Difficulty:IntermediateLength:LongLanguages:

Ukrainian (українська мова) translation by Nadia Gonzales (you can also view the original English article)

Реалізація надійної стратегії автентифікації для будь-якого застосунку може бути надзвичайно важкою задачею, і Node-застосунки – не виняток.

У цьому посібнику ми розробимо застосунок Node.js з нуля та будемо використовувати нове, але дуже популярне ПЗ (* програмне забезпечення. Тут і надалі примітка перекладача) проміжного шару для реалізації автентифікації  – Passport для вирішення наших питань із аутентифікацією.

В документації по Passport воно описується як «просте невибагливе ПЗ проміжного шару для реалізації автентифікації Node-застосунків», і вірно.

Постачаючись як ПЗ проміжного шару, Passport відмінно упорується з розділом питань автентифікації від інших. Завдяки цьому Passport можна легко вбудовувати до будь-якого веб-додатку на основі Express настільки ж легко як ми вбудовуємо інше ПЗ проміжного шару для Express, наприклад, для забезпечення входу до системи, розбору тіла запиту, розбору кукі, реалізації сесії тощо.

У посібнику припускається, що ви маєте базові уявлення про Node.js та фреймворк Express, і робиться спроба звернути увагу на реалізацію автентифікації, хоча ми й створимо приклад застосунку Express з нуля та покращимо його, додавши маршрути та реалізувавши аутентифікацію для деяких із них.

Стратегії автентифікації

Passport надає нам можливість вибору з більш ніж 140 способів автентифікації. Ви можете реалізувати автентифікацію за допомогою локального/віддаленого екземпляра бази даних, чи використовувати SSO (* single sign-on – технологія єдиного входу) за допомогою провайдерів OAuth (* відкритий стандарт авторизації, який дозволяє користувачам відкривати доступ до своїх приватних даних (фотографії, відео, списки контактів), що зберігаються на одному сайті, іншому сайту, без необхідності вводу імені користувача та паролю) для Facebook, Twitter, Google і т. ін. для автентифікації користувачів за допомогою їх акаунтів у соціальних мережах, чи ви маєте можливість вибрати з великого списку провайдерів, що підтримують автентифікацію за допомогою Passport та надають для цього відповідний модуль Node.

Проте не турбуйтеся: вам нема необхідності підключати будь-які стратегії, що не потрібні для вашого застосунку. Всі ці стратегії не залежать одна від одної та реалізовані у вигляді окремих модулів Node, що не підключаються за налаштуванням при встановленні Passport за допомогою npm install passport.

У цьому посібнику ми будемо використовувати локальну стратегію автентифікації Passport і здійснювати автентифікацію користувачів за допомогою локально налаштованого екземпляру MongoDB, зберігаючи дані користувачів до бази даних. Для використання локальної стратегії автентифікації нам необхідно встановити модуль passport-local за допомогою npm install passport-local.

Але зачекайте: До того як ви запустите вашу консоль та почнете виконувати ці команди, давайте почнемо зі створення застосування Express з нуля та додамо декілька маршрутів до нього (для входу до застосування, реєстрації та головної сторінки) і потім спробуємо додати до нього наше ПЗ проміжного шару для реалізації автентифікації. Зверніть увагу, що у цілях цього посібника ми будемо використовувати Express 4, проте з невеликими поправками Passport також буде працювати й з Express 3.

Встановлення застосунку

Якщо ви ще цього не зробили, то встановіть Express і express-generator для створення шаблону застосунку просто за допомогою виконання в консолі express passport-mongo. Структура створеного застосунку повинна виглядати наступним чином:

Initial Application Structure

авайте усунемо деякі функціональні можливості, що ми не будемо використовувати: видаліть файл users.js та посилання на нього з файлу app.js.

Додавання залежностей проекту

Відкрийте package.json та додайте залежності для модулів passport та passport-local.

Оскільки ми будемо зберігати дані користувачів до MongoDB, то будемо використовувати Mongoose (* ODM (Object Document Mapper - об'єктно-документний відображувач)) у якості інструмента для моделювання об'єктних даних. Встановити та зберегти залежності до package.json можна й таким чином:

package.json повинен виглядати наступним чином:

Added Mongoose Dependencies

Тепер встановіть усі залежності та запустіть шаблон застосунку за допомогою npm install && npm start. У результаті цього буде завантажено та встановлено всі залежності та запущено сервер Node. Ви можете ознайомитися з базовим застосунком Express за адресою http://localhost:3000/, проте там ні на що дивитися.

Дуже скоро ми змінимо це, коли створимо повноцінний застосунок Express, що надає сторінку реєстрації для нового користувача, сторінку входу для зареєстрованого користувача та здійснює автентифікацію зареєстрованого користувача за допомогою Passport.

Створення моделі Mongoose

Оскільки ми будемо зберігати дані користувача до Mongo, то давайте створимо модель User в Mongoose та збережемо її до models/user.js нашого застосунку.

По суті, ми створюємо модель Mongoose, за допомогою якої ми можемо виконувати операції CRUD (* create, read, update, delete - створити, прочитати, оновити, видалити) над даними бази, що лежить в основі.

Налаштування Mongo

Якщо у вас не встановлена локально Mongo, то ми рекомендуємо вам використовувати хмарні сервіси надання баз даних, наприклад, Modulus или MongoLab. Створити робочий екземпляр MongoDB за допомогою них можна не тільки безкоштовно, але й усього за декілька клацань.

Після створення бази даних на одному з цих сервісів вам буде надано URI на зразок наступного: mongodb://:@novus.modulusmongo.net:27017/, який можна використовувати для здійснення операцій CRUD над базами даних. Рекомендується зберігати конфігурацію бази даних в окремому файлі, що можна підключити за необхідності. Тому ми створюємо модуль Node db.js, який виглядає наступним чином:

Якщо ви схожі на мене та використовуєте локальний екземпляр Mongo, то прийшов час запустити демон (* прихований від користувача процес (часто виконуваний у фоновому режимі), який викликають під час виконання якоїсь функції (або в конкретний момент часу)) mongoddb.js повинен виглядати наступним чином:

Тепер ми використовуємо цю конфігурацію в app.js і підключаємося до бази даних за допомогою Mongoose API:

Налаштування Passport

Passport надає тільки механізм для реалізації автентифікації і покладає відповідальність за реалізацію підтримки сесій на нас; для цього ми будемо використовувати модуль express-session. Відкрийте app.js і вставте наведений нижче код перед налаштуванням маршрутів:


Це необхідно для забезпечення стабільності нашої сесії на сайті. До запуску застосунку нам необхідно встановити express-session та додати його до нашого списку залежностей у package.json. Для цього виконайте npm install --save express-session

Серіалізація та десеріалізація екземплярів користувачів

Для Passport також необхідно забезпечити серіалізацію та десеріалізацію екземплярів користувачів із сховища для сесій, щоб підтримувати сесії входу таким чином, що кожний наступний запит не буде містити мандат (* обліковий запис із параметрами доступу користувача, створеними після його вдалої автентифікації) користувача. Для цього Passport має методи serializeUser і  deserializeUser:

Використання стратегій Passport

Зараз ми визначимо стратегії Passport для реалізації можливостей входу до застосунку та реєстрації. Кожна з них буде екземпляром Local Authentication Strategy (* локальної стратегії автентифікації) Passport та буде створена за допомогою функції passport.use(). . Ми використовуємо модуль connect-flash, який допомагає нам в обробленні помилок, надаючи флеш-повідомлення, які можуть бути показані користувачеві у разі помилки.

Стратегія входу до застосунку

Стратегія входу до застосунку виглядає наступним чином:

Перший параметр passport.use() – це ім'я стратегії, яке буде використовуватися для розпізнавання цієї стратегії при подальшому використанні. Другий параметр – це тип стратегії, яку ви хочете створити; тут ми використовуємо тип username-password, чи LocalStrategy. Варто зазначити, що за налаштуванням LocalStrategy буде шукати мандат користувача в параметрах username і password, але також цей тип дозволяє використовувати будь-які інші іменовані параметри.  Змінна конфігурації passReqToCallback дозволяє нам отримати доступ до об'єкта запиту в функції зворотного виклику, таким чином надаючи нам можливість використання будь-якого параметра, доступного в об'єкті запиту.

Далі ми використовуємо API Mongoose для пошуку даного користувача в нашій головній колекції Users, щоб перевірити, чи існує він у базі даних. Останній параметр у нашій функції зворотного виклику, done, являє собою корисний метод, за допомогою якого ми мали би можливість сигналізувати модулю Passport про успіх або невдачу. Щоб повідомити про невдачу, необхідно, щоб або перший параметр містив помилку, або результатом обчислення значення другого параметра було значення false. Для повідомлення про успіх необхідно, щоб першим параметром було null і результатом обчислення значення другого параметра було значення truthy, у випадку чого воно буде доступен в объекте request.

Оскільки паролі ненадійні за соїм характером, нам необхідно завжди їх шифрувати перед зберіганням до бази даних. Для цього ми використовуємо модуль bcrypt-nodejs, який допомагає нам у шифруванні/дешифруванні паролів.

Якщо вам хотілося би подивитися на повний код у дії, а не на фрагменти коду, то ознайомтеся з кодом за посиланням.

Стратегія для реєстрації

Тепер ми визначаємо наступну стратегію, за допомогою якої реалізується можливість реєстрації нового користувача та створюється його чи її запис у MongoDB, що полягає в основі:

Тут ми знову використовуємо API Mongoose, щоб дізнатися, чи існує вже користувач із цим іменем або ні. Якщо ні, то створюємо нового користувача та зберігаємо інформацію про нього до Mongo. В іншому випадку повертаємо помилку, використовуючи функцію зворотного виклику done та флеш-повідомлення. Зверніть увагу на те, що ми використовуємо bcrypt-nodejs для створення гешу пароля перед зберіганням:

Створення маршрутів

Якщо би ми поглянули на наш додаток із висоти пташиного польоту, то він би виглядав наступним чином:

Birds Eye View of Our Application

Тепер ми визначаємо маршрути для нашого додатка в наступному модулі, який використовує екземпляр Passport, створений вище в app.js. Збережіть цей модуль до routes/index.js.

Найбільш важлива частина приведеного вище коду – це використання passport.authenticate() для доручення здійснення автентифікації стратегіям login и signup, коли відбуваються HTTP-запити по методу POST до маршрутів /login та /signup. Зверніть увагу, що додавання до назви шляхів маршрутів назв стратегій не є обов'язковим і може бути будь-яким.  Зверніть увагу, що додавання до назви шляхів маршрутів назв стратегій не є обов'язковим і може бути будь-яким.

Створення представлень на Jade (* перейменований у Pug)

Далі створюємо наступні два представлення для нашого додатка:

  1. в layout.jade міститься базовий макет та інформація про стильове оформлення
  2. в index.jade міститься сторінка входу, що надає форму для входу та можливість створити новий акаунт

Завдяки Bootstrap (* веб-фреймворк для дизайну веб-сайтів та веб-додатків) наша сторінка для входу виглядає наступним чином:

Login Page for Our Passport App

Нам ще необхідні представлення для заповнення реєстраційних даних і для домашньої сторінки нашого додатка:

  1. в register.jade міститься форма для реєстрації
  2. в home.jade виводиться привітання та наводяться дані користувача, що увійшов

Якщо погано знаєте Jade , то ознайомтесь із документацією.

Реалізація функціональної можливості виходу із додатка

Passport, будучи ПЗ проміжного шару, має можливість додавати певні властивості та методи до об'єктів запиту та відповіді і вдало її використовує, додаючи дуже корисний метод request.logout(), що дозволяє зробити недійсною тільки сесію на сайті, не чіпаючи інші можливості.

Захист маршрутів

Passport  також надає можливість захистити доступ до маршруту, доступ до якого необхідно обмежити для анонімних користувачів. Це означає, що у випадку отримання доступу якого-небудь користувача до http://localhost:3000/home без проходження автентифікації в застосунку його буде переадресовано до початкової сторінки за допомогою:

Завершення

Passport не єдиний гравець на арені, коли мова заходить про автентифікацію додатків Node.js. Існують альтернативи, наприклад, EveryAuth, проте завдяки принципу модульності, гнучкості, підтримці товариства та факту, що Passport – це ПЗ проміжного шару, обговорюваний у посібнику модуль є більш вдалим вибором.

Ось порівняння цих двох варіантів від самого розробника Passport.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.