Аутентификация в Node.js с использованием Passport.js

В этой стаье вы узнаете, как реализовать стратегию локальной аутентификации в Node.js приложении с использованием Passport.js и Redis.

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

Что такое Passport.js?

Простая, ненавязчивая аутентификация для Node.js — passportjs.org

Passport — это middleware для проверки подлинности, которую мы собираемся использовать для управления сессиями.

Что такое Redis?

Redis это опенсорс (лицензии BSD) хранилище структур данных в оперативной памяти, используемое как база данных, кэш и брокер сообщений — redis.io

Мы собираемся хранить информацию о сессии пользователя в Redis, а не в памяти процесса. Таким образом, наше приложение будет намного проще масштабировать.

Демонстрационное приложение

Для демонстрационных целей создадим приложение, которое умеет только следующее:

  • предоставляет форму входа
  • предоставляет две защищённые страницы
  • страницу профиля
  • безопасные заметки

Структура проекта

Вы уже научились структурировать Node.js-проекты в предыдущей главе Node Hero, поэтому давайте использовать эти знания!

Мы собираемся использовать следующую структуру:

├── app
| ├── authentication
| ├── note
| ├── user
| ├── index.js
| └── layout.hbs
├── config
| └── index.js
├── index.js
└── package.json

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

(Вы можете скачать исходный код по ссылке https://github.com/RisingStack/nodehero-authentication)

Процесс аутентификации в Node.js

Наша цель — реализовать в нашем приложении следующий процесс аутентификации:

  1. Пользователь вводит имя и пароль
  2. Приложение проверяет, являются ли они корректными
  3. Если имя и пароль корректны, приложение отправляет заголовок Set-Cookie, который будет использоваться для аутентификации дальнейших страниц
  4. Когда пользователь посещает страницы в том же домене, ранее установленный cookie будет добавлен ко всем запросам
  5. Аутентификация на закрытых страницах происходит с помощью этого файла cookie

Чтобы настроить такую стратегию аутентификации, выполните следующие три действия:

  1. Настройте Express
  2. Настройте Passport
  3. Добавьте защищённые разделы на сайте

Шаг 1: Настройка Express

Мы будем использовать Express для серверной среды — вы можете узнать больше на эту тему, перечитав главу «Ваш первый сервер на Node.js».

// file:app/index.js
const express = require('express')
const passport = require('passport')
const session = require('express-session')
const RedisStore = require('connect-redis')(session)
const app = express()
app.use(session({
store: new RedisStore({
url: config.redisStore.url
}),
secret: config.redisStore.secret,
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())

Что мы тут делаем?

Прежде всего, нам нужны все зависимости, которые требуются для управления сессией. После этого мы создали новый экземпляр из модуля express-session, который будет хранить наши сессии.

Для хранения сессий мы используем Redis, но вы можете использовать любые другие, такие как MySQL или MongoDB.

Шаг 2: Настройка Passport

Passport — отличный пример библиотеки, использующей плагины. В этом уроке мы добавляем модуль passport-local, который добавляет простую локальную стратегию аутентификации с использованием имён пользователей и паролей.

Для простоты в этом примере (см. ниже) мы не используем базу данных, вместо неё используется экземпляр объекта пользователя в памяти. В реальных приложениях findUser будет искать пользователя в базе данных.

// file:app/authenticate/init.js
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const user = {
username: 'test-user',
password: 'test-password', id: 1
}
passport.use(new LocalStrategy(
function(username, password, done) {
findUser(username, function (err, user) {
if (err) {
return done(err)
}
if (!user) {
return done(null, false)
}
if (password !== user.password ) {
return done(null, false)
}
return done(null, user)
})
}
))

Как только findUser возвращается с нашим объектом пользователя, остаётся только сравнить введённый пользователем и реальный пароль, чтобы увидеть, есть ли совпадение.

Если они совпадают, мы разрешаем пользователю войти (возвращая объект пользователь в passport - return done(null, user)), если нет — возвращаем ошибку авторизации(путём возврата null - return done(null)).

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

Шаг 3: Добавляем защищённые разделы на сайте

Чтобы добавить защищенные разделы на сайт, мы используем шаблон middleware Express. Для этого сначала создадим middleware для аутентификации:

// file:app/user/init.js
const passport = require('passport')
app.get('/profile', passport.authenticationMiddleware(), renderProfile)

Она имеет только одну задачу — если пользователь аутентифицирован (имеет правильные cookie-файлы), она просто вызывает следующую middleware. В противном случае пользователь перенаправляется на страницу, где он может войти в систему.

Использование этой middleware также просто, как добавление любой другой middleware в определение роута.

// file:app/authentication/middleware.js
function authenticationMiddleware () {
return function (req, res, next) {
if (req.isAuthenticated()) {
return next()
}
res.redirect('/')
}
}

Резюме

В этом разделе учебника по Node.js вы узнали, как добавить базовую аутентификацию в ваше приложение. Позже вы можете расширить его с помощью различных стратегий аутентификации, таких как Facebook или Twitter. Вы можете найти больше стратегий по адресу http://passportjs.org/.

Полный рабочий пример нашего демонстрационного приложения вы можете найти на GitHub: https://github.com/RisingStack/nodehero-authentication

NodeJs
29.04.2018
1 ответ
авторизуйтесь чтобы ответить