Как настроить аутентификацию по паспорту в приложении Node и Postgres

29
технологии 28.webp

Последнее обновление 11.01.2023 — Василий Иванов

Как разработчик, вы несете ответственность за защиту данных ваших пользователей с помощью аутентификации. Вы можете использовать Passport.js для аутентификации пользователей в приложениях Node и Postgres.

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

Создание таблицы пользователей

Для аутентификации пользователя вы будете использовать адрес электронной почты и пароль. Это означает, что таблица пользователей должна содержать поле электронной почты и пароль. В командной строке psql создайте новую базу данных с именем nodeapp:

CREATE DATABASE nodeapp;

Затем создайте таблицу для хранения пользователей:

CREATE TABLE users (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
email CHAR(128),
password CHAR(60)
);

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

По теме:  Нашли потерянный телефон? Как вернуть его владельцу за 7 простых шагов

Создание узлового сервера

Node.js — это серверная среда выполнения JavaScript, которая позволяет нам быстро создавать HTTP-серверы. Чтобы упростить процесс создания сервера и различных HTTP-маршрутов, вы можете использовать Express, веб-фреймворк Node.js.

Запустите эту команду, чтобы создать новую папку с именем postgres-auth:

mkdir postgres-auth

Далее инициализируем npm:

npm init -y

Наконец, установите Express:

npm install express

Теперь вы можете создать веб-сервер Node.

В новый файл с именем index.js добавьте следующее:

const express = require("express");
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.listen(3000, () => console.log("Listening on port 3000"));

Запуск этого кода запустит сервер и выведет в консоль следующее:

Listening on port 3000

Подключение к PostgreSQL.

Для подключения к PostgreSQL используйте node-postgres. node-postgres — это драйвер соединения, обеспечивающий интерфейс между Node и Postgres.

Выполните следующее, чтобы установить node-postrges через npm:

npm install pg

После того, как вы установили эту библиотеку, создайте новый файл с именем db.js и подключите его к базе данных:

const { Client } = require("pg");
const { user, host, database, password, port } = require("./dbConfig");

const client = new Client({
user,
host,
database,
password,
port,
});

client.connect();
module.exports = client;

Клиентский метод из node-postgres получает информацию о базе данных, к которой вы подключаетесь. Эта программа импортирует данные о подключении из файла с именем dbConfig. Поэтому создайте этот файл и добавьте в него следующий код:

module.exports = {
user: "postgres",
host: "localhost",
database: "nodeapp",
password: "yourPassword",
port: 5432,
};

Создание вспомогательных функций базы данных

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

  1. Чтобы проверить, зарегистрирована ли электронная почта.
  2. Создать пользователя.

Цель состоит в том, чтобы зарегистрировать пользователя только в том случае, если он не существует в базе данных.

Создайте новый файл с именем helper.js и импортируйте клиент базы данных из db.js:

const client = require("./db.js")

Затем добавьте новую функцию с именем emailExists():

const emailExists = async (email) => {
const data = await client.query("SELECT * FROM users WHERE email=$1", [
email,
]);

if (data.rowCount == 0) return false;
return data.rows[0];
};

Эта функция принимает электронное письмо и проверяет, не используется ли оно уже. Для этого используется предложение SELECT, которое возвращает строку с полем электронной почты, совпадающим со значением, предоставленным регистрирующимся пользователем. Если адрес электронной почты не существует, он возвращает false.

Чтобы создать функцию, создающую пользователя, добавьте функцию createUser() в helper.js:

const createUser = async (email, password) => {
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);

const data = await client.query(
"INSERT INTO users(email, password) VALUES ($1, $2) RETURNING id, email, password",
[email, hash]
);

if (data.rowCount == 0) return false;
return data.rows[0];
};

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

Установите bcryptjs, чтобы начать его использовать:

npm install bcryptjs

В helper.js импортируйте bcryptjs:

const bcrypt = require("bcryptjs")

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

Создайте функцию с именем matchPassword():

const matchPassword = async (password, hashPassword) => {
const match = await bcrypt.compare(password, hashPassword);
return match
};

Он получает простой пароль и хэш, а затем использует Bcrypt.compare() для определения правильности предоставленного пароля. Если это так, он возвращает true, иначе возвращает false.

Это все функции, которые мы будем использовать для взаимодействия с базой данных. Обязательно экспортируйте их все в конце:

module.exports = { emailExists, createUser, matchPassword };

Настроить паспорт

Passport — это промежуточное ПО для аутентификации Node, которое предоставляет более 500 стратегий аутентификации, таких как вход через социальные сети, веб-токены JSON (JWT) и аутентификация по электронной почте. Мы будем использовать последний вариант, который обеспечивает стратегия «паспортно-локальный».

Используйте следующую команду для установки паспорта и паспорта-местного:

npm install passport
npm install passport-local

Затем настройте Passport для входа в систему существующих пользователей и регистрации новых пользователей.

Начните с создания нового файлаpassportConfig.js. Затем импортируйте локальную стратегию Passport и только что созданные вспомогательные функции базы данных:

const LocalStrategy = require("passport-local");
const { emailExists, createUser, matchPassword } = require("./helper");

В том же файле добавьте следующее для настройки регистрации пользователя:

module.exports = (passport) => {
passport.use(
"local-signup",
new LocalStrategy(
{
usernameField: "email",
passwordField: "password",
},
async (email, password, done) => {
try {
const userExists = await emailExists(email)

if (userExists) {
return done(null, false);
}

const user = await createUser(email, password);
return done(null, user);
} catch (error) {
done(error);
}
}
)
);
}

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

Эта программа сначала проверяет, занято ли электронное письмо, используя функцию emailExists() из helper.js. Если адрес электронной почты не существует в базе данных, он создает нового пользователя с помощью функции createUser(). Наконец, он возвращает пользовательский объект.

Чтобы войти в систему, добавьте следующее вpassportConfig.js:

module.exports = (passport) => {
passport.use(
"local-signup",
new LocalStrategy(
// sign up
)
);
passport.use(
"local-login",
new LocalStrategy(
{
usernameField: "email",
passwordField: "password",
},
async (email, password, done) => {
try {
const user = await emailExists(email);
if (!user) return done(null, false);
const isMatch = await matchPassword(password, user.password);
if (!isMatch) return done(null, false);
return done(null, {id: user.id, email: user.email});
} catch (error) {
return done(error, false);
}
}
)
);
};

Здесь программа сначала проверяет, зарегистрирована ли электронная почта. Если нет, возвращает false. Если он находит письмо, он сравнивает свой пароль с паролем из запроса. Если пароли совпадают, он регистрирует пользователя и возвращает объект пользователя.

Последним шагом является создание конечных точек API:

  • ПОСТ/авторизация/регистрация
  • ПОСТ/авторизация/логин

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

Импортируйте и настройте Passport в новом файле с именем server.js:

const passport = require("passport");
require("./passportConfig")(passport);

Затем добавьте следующие маршруты:

app.post(
"/auth/signup",
passport.authenticate("local-signup", { session: false }),
(req, res, next) => {
res.json({
user: req.user,
});
}
);
app.post(
"/auth/login",
passport.authenticate("local-login", { session: false }),
(req, res, next) => {
res.json({ user: req.user });
}
);

Оба этих маршрута в случае успеха возвращают объект JSON, содержащий пользователя.

Проверьте свой API с помощью модульных тестов

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

Хотя вы можете использовать клиенты REST, такие как Postman, для проверки того, насколько хорошо работает API, написание модульных тестов намного проще. Модульные тесты позволяют тестировать отдельные части вашего приложения. Таким образом, даже если конечная точка выйдет из строя, вы сможете определить точную точку отказа. Одним из инструментов, которые вы можете использовать для тестирования приложений Node, является Jest.