В веб-приложениях обработка паролей требует обязательного применения криптографического хеширования до их сохранения. В экосистеме Node.js одной из наиболее распространённых библиотек для этой задачи является bcrypt.js — реализация алгоритма bcrypt, адаптированная для JavaScript и работающая как в серверной среде Node.js, так и в браузере.
Основная задача middleware в Express.js в контексте паролей — перехват входящих данных пользователя и преобразование открытого пароля в безопасный хеш перед сохранением в базу данных.
Библиотека устанавливается стандартным способом через npm:
npm install bcryptjs
После установки доступ к функционалу осуществляется через импорт:
const bcrypt = require('bcryptjs');
Алгоритм bcrypt основан на адаптивной функции хеширования, которая включает:
Ключевое свойство — невозможность восстановления исходного пароля из хеша.
Middleware в Express.js представляет собой функцию, которая получает
доступ к объектам запроса и ответа, а также управляет потоком выполнения
через next().
В контексте хеширования паролей middleware используется как промежуточный слой между получением данных от клиента и сохранением их в базу данных.
const bcrypt = require('bcryptjs');
const hashPasswordMiddleware = async (req, res, next) => {
try {
const password = req.body.password;
if (!password) {
return res.status(400).json({ message: 'Пароль отсутствует' });
}
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(password, saltRounds);
req.body.password = hashedPassword;
next();
} catch (error) {
return res.status(500).json({ message: 'Ошибка хеширования пароля' });
}
};
Middleware подключается на уровне маршрута:
const express = require('express');
const app = express();
app.use(express.json());
app.post('/register', hashPasswordMiddleware, async (req, res) => {
const user = {
email: req.body.email,
password: req.body.password
};
// сохранение пользователя в базу данных
res.status(201).json({ message: 'Пользователь создан' });
});
Параметр salt rounds определяет сложность вычислений. Чем выше значение, тем медленнее вычисляется хеш, но выше безопасность.
const saltRounds = 12;
Альтернативный способ явной генерации соли:
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);
Хеширование используется только при создании или обновлении пароля. При логине выполняется сравнение:
const isMatch = await bcrypt.compare(plainPassword, hashedPassword);
if (!isMatch) {
return res.status(401).json({ message: 'Неверный пароль' });
}
В реальных приложениях логика хеширования и проверки разделяется:
Пример структуры:
// middleware
const hashPassword = async (req, res, next) => {
req.body.password = await bcrypt.hash(req.body.password, 10);
next();
};
// login service
const validatePassword = async (password, hash) => {
return await bcrypt.compare(password, hash);
};
При использовании ORM (например, Sequelize или Mongoose) хеширование часто переносится на уровень модели.
Пример с Mongoose:
const userSchema = new mongoose.Schema({
email: String,
password: String
});
userSchema.pre('save', async function (next) {
if (!this.isModified('password')) return next();
this.password = await bcrypt.hash(this.password, 10);
next();
});
Такой подход уменьшает зависимость от middleware Express.js и повышает целостность логики.
На практике часто встречаются следующие проблемы:
bcrypt.js использует CPU-интенсивные операции. При высокой нагрузке важно:
Асинхронный вариант:
await bcrypt.hash(password, 10);
Синхронный вариант:
bcrypt.hashSync(password, 10);
Синхронные методы блокируют event loop и не подходят для production-среды с высокой нагрузкой.
Правильная организация слоя Express.js обычно включает:
Хеширование не должно смешиваться с бизнес-логикой или контроллерами напрямую.
/controllers
/middleware
/services
/models
/routes
Middleware для bcrypt.js обычно располагается отдельно:
/middleware/hashPassword.js
При смене пароля важно повторно применять хеширование:
app.put('/user/password', async (req, res) => {
const newPassword = req.body.password;
const hashed = await bcrypt.hash(newPassword, 10);
// обновление в базе
});
Алгоритм bcrypt включает:
Это делает его устойчивым к brute-force атакам по сравнению с устаревшими алгоритмами (например, MD5 или SHA1).