Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Node.js
Code

Аутентификация Node-приложений при помощи Passport

by
Difficulty:IntermediateLength:LongLanguages:

Russian (Pусский) 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://<dbuser>:<dbpassword>@novus.modulusmongo.net:27017/<dbName>, который можно использовать для осуществления операций 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, в случае чего оно будет доступно в объекте запроса.

Поскольку пароли ненадежны по своей природе, нам необходимо всегда их шифровать перед сохранением в базу данных. Для этого мы используем модуль 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. в ndex.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
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.