Библиотека Iron в экосистеме JavaScript используется для шифрования и подписи данных, чаще всего — для безопасного хранения информации в cookie. В Node.js она распространяется через npm и устанавливается как отдельный модуль.
Установка выполняется стандартной командой:
npm install @hapi/iron
После установки модуль становится доступным для подключения через
require или import, в зависимости от
используемой системы модулей.
const Iron = require('@hapi/iron');
В ESM-окружении:
import Iron from '@hapi/iron';
Библиотека реализует механизм «запечатывания» (seal) и «распечатывания» (unseal) данных. В отличие от обычного шифрования, результатом является строка, которая одновременно:
Чаще всего используется для безопасного хранения JSON-данных в cookie, когда необходимо исключить возможность их изменения на стороне клиента.
Любая операция с Iron требует криптографического ключа. Он должен быть достаточно сложным и храниться на сервере.
Пример ключа:
const key = 'a-very-long-and-secure-random-secret-key';
В реальных приложениях ключ обычно берётся из переменных окружения:
const key = process.env.IRON_SECRET;
Перед записью в cookie данные преобразуются в защищённую строку с
помощью метода seal.
const Iron = require('@hapi/iron');
const sessionData = {
userId: 42,
role: 'admin'
};
const password = 'a-very-long-and-secure-random-secret-key';
async function createCookieValue() {
const sealed = await Iron.seal(sessionData, password, Iron.defaults);
return sealed;
}
Результат — строка, содержащая зашифрованные данные и метаданные целостности.
После получения зашифрованного значения его можно записать в HTTP-ответ:
const http = require('http');
http.createServer(async (req, res) => {
const password = process.env.IRON_SECRET;
const data = {
userId: 42,
role: 'admin'
};
const sealed = await Iron.seal(data, password, Iron.defaults);
res.setHeader('Set-Cookie', `session=${sealed}; HttpOnly; Secure; Path=/`);
res.end('Cookie установлен');
});
Флаги cookie:
HttpOnly — запрет доступа из JavaScriptSecure — передача только по HTTPSPath=/ — доступность на всём сайтеДля извлечения данных необходимо:
Iron.unsealfunction parseCookies(req) {
const header = req.headers.cookie;
const result = {};
if (!header) {
return result;
}
header.split(';').forEach(cookie => {
const parts = cookie.split('=');
const key = parts[0].trim();
const value = parts[1];
result[key] = value;
});
return result;
}
const Iron = require('@hapi/iron');
async function readCookie(req) {
const cookies = parseCookies(req);
const sealed = cookies.session;
if (!sealed) {
return null;
}
const password = process.env.IRON_SECRET;
const unsealed = await Iron.unseal(sealed, password, Iron.defaults);
return unsealed;
}
После выполнения unseal возвращается исходный
объект:
{
userId: 42,
role: 'admin'
}
Строка, создаваемая Iron, содержит несколько слоёв защиты:
Это делает невозможным:
Iron позволяет задавать параметры защиты через
options.
const options = {
ttl: 24 * 60 * 60 * 1000, // 1 день
timestampSkewSec: 60,
localtimeOffsetMsec: 0
};
Применение:
const sealed = await Iron.seal(data, password, options);
TTL ограничивает срок жизни данных, после чего unseal
вызовет ошибку.
При работе с cookie важно учитывать возможные ошибки:
try {
const data = await Iron.unseal(sealed, password, Iron.defaults);
} catch (err) {
// данные повреждены или истёк срок действия
}
Типичные причины ошибок:
Пример полного цикла работы:
const http = require('http');
const Iron = require('@hapi/iron');
const secret = process.env.IRON_SECRET;
http.createServer(async (req, res) => {
const cookies = parseCookies(req);
let session = null;
if (cookies.session) {
try {
session = await Iron.unseal(cookies.session, secret, Iron.defaults);
} catch (e) {
session = null;
}
}
if (!session) {
const newSession = {
userId: 1,
role: 'guest'
};
const sealed = await Iron.seal(newSession, secret, Iron.defaults);
res.setHeader('Set-Cookie', `session=${sealed}; HttpOnly; Path=/`);
res.end('Новая сессия создана');
return;
}
res.end(`Пользователь ${session.userId}`);
}).listen(3000);
Использование Iron в cookie-хранилище отличается от обычного шифрования тем, что:
Это упрощает архитектуру, но накладывает ограничения на размер данных и необходимость аккуратного управления ключами.