session: Библиотека сессий для nginx-module-lua – гибкая и безопасная
Установка
Если вы еще не настроили подписку на RPM-репозиторий, зарегистрируйтесь. Затем вы можете продолжить, выполнив следующие шаги.
CentOS/RHEL 7 или Amazon Linux 2
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-session
CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-session
Чтобы использовать эту библиотеку Lua с NGINX, убедитесь, что установлен nginx-module-lua.
В этом документе описывается lua-resty-session v4.2.0, выпущенная 24 августа 2026 года.
lua-resty-session — это безопасная и гибкая библиотека сессий для OpenResty.
TL;DR;
- Сессии неизменяемы (каждое сохранение создает новую сессию) и не используют блокировки.
- Данные сессии шифруются с помощью AES-256-GCM с ключом, полученным с использованием HKDF-SHA256 (в FIPS-режиме вместо этого используется PBKDF2 с SHA-256).
- Сессия имеет заголовок фиксированного размера, который защищен с помощью HMAC-SHA256 MAC с ключом, полученным с использованием HKDF-SHA256 (в FIPS-режиме вместо этого используется PBKDF2 с SHA-256).
- Данные сессии могут храниться в cookie без сохранения состояния или в различных серверных хранилищах.
- Один cookie сессии может поддерживать несколько сессий для разных аудиторий.
Примечание: Версия 4.0.0 была переписыванием этой библиотеки с учетом многих уроков, извлеченных за эти годы. Если вы все еще используете более старую версию, обратитесь к старой документации.
Синопсис
worker_processes 1;
events {
worker_connections 1024;
}
http {
init_by_lua_block {
require "resty.session".init({
remember = true,
audience = "demo",
secret = "RaJKp8UQW1",
storage = "cookie",
})
}
server {
listen 8080;
server_name localhost;
default_type text/html;
location / {
content_by_lua_block {
ngx.say([[
<html>
<body>
<a href=/start>Start the test</a>
</body>
</html>
]])
}
}
location /start {
content_by_lua_block {
local session = require "resty.session".new()
session:set_subject("OpenResty Fan")
session:set("quote", "The quick brown fox jumps over the lazy dog")
local ok, err = session:save()
ngx.say(string.format([[
<html>
<body>
<p>Session started (%s)</p>
<p><a href=/started>Check if it really was</a></p>
</body>
</html>
]], err or "no error"))
}
}
location /started {
content_by_lua_block {
local session, err = require "resty.session".start()
ngx.say(string.format([[
<html>
<body>
<p>Session was started by %s (%s)</p>
<p><blockquote>%s</blockquote></p>
<p><a href=/modify>Modify the session</a></p>
</body>
</html>
]],
session:get_subject() or "Anonymous",
err or "no error",
session:get("quote") or "no quote"
))
}
}
location /modify {
content_by_lua_block {
local session, err = require "resty.session".start()
session:set_subject("Lua Fan")
session:set("quote", "Lorem ipsum dolor sit amet")
local _, err_save = session:save()
ngx.say(string.format([[
<html>
<body>
<p>Session was modified (%s)</p>
<p><a href=/modified>Check if it is modified</a></p>
</body>
</html>
]], err or err_save or "no error"))
}
}
location /modified {
content_by_lua_block {
local session, err = require "resty.session".start()
ngx.say(string.format([[
<html>
<body>
<p>Session was started by %s (%s)</p>
<p><blockquote>%s</blockquote></p>
<p><a href=/destroy>Destroy the session</a></p>
</body>
</html>
]],
session:get_subject() or "Anonymous",
err or "no error",
session:get("quote") or "no quote"
))
}
}
location /destroy {
content_by_lua_block {
local ok, err = require "resty.session".destroy()
ngx.say(string.format([[
<html>
<body>
<p>Session was destroyed (%s)</p>
<p><a href=/destroyed>Check that it really was?</a></p>
</body>
</html>
]], err or "no error"))
}
}
location /destroyed {
content_by_lua_block {
local session, err = require "resty.session".open()
ngx.say(string.format([[
<html>
<body>
<p>Session was really destroyed, you are known as %s (%s)</p>
<p><a href=/>Start again</a></p>
</body>
</html>
]],
session:get_subject() or "Anonymous",
err or "no error"
))
}
}
}
}
Конфигурация
Конфигурацию можно разделить на общую конфигурацию сессии и конфигурацию серверного хранилища.
Вот пример:
init_by_lua_block {
require "resty.session".init({
remember = true,
store_metadata = true,
secret = "RaJKp8UQW1",
secret_fallbacks = {
"X88FuG1AkY",
"fxWNymIpbb",
},
storage = "postgres",
postgres = {
username = "my-service",
password = "kVgIXCE5Hg",
database = "sessions",
},
})
}
Конфигурация сессии
Конфигурация сессии может быть передана в функции инициализации, конструкторы и вспомогательные функции.
Вот возможные параметры конфигурации сессии:
| Параметр | По умолчанию | Описание |
|---|---|---|
secret |
nil |
Секрет, используемый для получения ключа. Секрет хешируется с помощью SHA-256 перед использованием. Например, "RaJKp8UQW1". |
secret_fallbacks |
nil |
Массив секретов, которые можно использовать в качестве альтернативных секретов (при ротации ключей), например, { "6RfrAYYzYq", "MkbTkkyF9C" }. |
ikm |
(случайный) | Начальный ключевой материал (или ikm) может быть указан напрямую (без использования секрета) ровно 32 байта данных. Например, "5ixIW4QVMk0dPtoIhn41Eh1I9enP2060" |
ikm_fallbacks |
nil |
Массив начальных ключевых материалов, которые можно использовать в качестве альтернативных ключей (при ротации ключей), например, { "QvPtlPKxOKdP5MCu1oI3lOEXIVuDckp7" }. |
cookie_prefix |
nil |
Префикс cookie, используйте nil, "__Host-" или "__Secure-". |
cookie_name |
"session" |
Имя cookie сессии, например, "session". |
cookie_path |
"/" |
Путь cookie, например, "/". |
cookie_domain |
nil |
Домен cookie, например, "example.com" |
cookie_http_only |
true |
Пометить cookie как HTTP only, используйте true или false. |
cookie_secure |
nil |
Пометить cookie как secure, используйте nil, true или false. |
cookie_priority |
nil |
Приоритет cookie, используйте nil, "Low", "Medium" или "High". |
cookie_same_site |
"Lax" |
Политика same-site для cookie, используйте nil, "Lax", "Strict", "None" или "Default" |
cookie_same_party |
nil |
Пометить cookie флагом same party, используйте nil, true или false. |
cookie_partitioned |
nil |
Пометить cookie флагом partitioned, используйте nil, true или false. |
remember |
false |
Включить или отключить постоянные сессии, используйте nil, true или false. |
remember_safety |
"Medium" |
Сложность получения ключа для remember cookie, используйте nil, "None" (быстро), "Low", "Medium", "High" или "Very High" (медленно). |
remember_cookie_name |
"remember" |
Имя cookie постоянной сессии, например, "remember". |
audience |
"default" |
Аудитория сессии, например, "my-application". |
subject |
nil |
Субъект сессии, например, "[email protected]". |
enforce_same_subject |
false |
Если установлено true, аудитории должны иметь одного и того же субъекта. Библиотека удаляет данные аудиторий, не соответствующих субъекту, при сохранении. |
stale_ttl |
10 |
Когда сессия сохраняется, создается новая сессия; stale ttl указывает, как долго старая сессия может еще использоваться, например, 10 (в секундах). |
idling_timeout |
900 |
Таймаут бездействия указывает, как долго сессия может быть неактивной, пока она не будет считаться недействительной, например, 900 (15 минут) (в секундах), 0 отключает проверки и обновление. |
rolling_timeout |
3600 |
Скользящий таймаут указывает, как долго сессия может использоваться, пока ее не нужно продлить, например, 3600 (час) (в секундах), 0 отключает проверки и продление. |
absolute_timeout |
86400 |
Абсолютный таймаут ограничивает, как долго сессия может продлеваться, пока не потребуется повторная аутентификация, например, 86400 (день) (в секундах), 0 отключает проверки. |
remember_rolling_timeout |
604800 |
Таймаут remember указывает, как долго постоянная сессия считается действительной, например, 604800 (неделя) (в секундах), 0 отключает проверки и продление. |
remember_absolute_timeout |
2592000 |
Абсолютный таймаут remember ограничивает, как долго постоянная сессия может продлеваться, пока не потребуется повторная аутентификация, например, 2592000 (30 дней) (в секундах), 0 отключает проверки. |
hash_storage_key |
false |
Хешировать или нет ключ хранилища. При хешированном ключе хранилища невозможно расшифровать данные на стороне сервера без наличия cookie, используйте nil, true или false. |
hash_subject |
false |
Хешировать или нет субъект, когда store_metadata включен, например, по причинам PII. |
store_metadata |
false |
Следует ли также хранить метаданные сессий, например, для сбора данных о сессиях для конкретной аудитории, принадлежащей конкретному субъекту. |
touch_threshold |
60 |
Порог touch контролирует, как часто или редко session:refresh обновляет cookie, например, 60 (минута) (в секундах) |
compression_threshold |
1024 |
Порог сжатия контролирует, когда данные сжимаются, например, 1024 (килобайт) (в байтах), 0 отключает сжатие. |
bind |
nil |
Привязать сессию к данным, полученным из HTTP-запроса или соединения, используйте ip, scheme, user-agent. Например, { "scheme", "user-agent" } будет вычислять MAC, также используя схему HTTP-запроса и заголовок User-Agent. |
request_headers |
nil |
Набор заголовков для отправки на вышестоящий сервер, используйте id, audience, subject, timeout, idling-timeout, rolling-timeout, absolute-timeout. Например, { "id", "timeout" } установит заголовки запроса Session-Id и Session-Timeout, когда вызывается set_headers. |
response_headers |
nil |
Набор заголовков для отправки клиенту, используйте id, audience, subject, timeout, idling-timeout, rolling-timeout, absolute-timeout. Например, { "id", "timeout" } установит заголовки ответа Session-Id и Session-Timeout, когда вызывается set_headers. |
storage |
nil |
Хранилище отвечает за хранение данных сессии, используйте nil или "cookie" (данные хранятся в cookie), "dshm", "file", "memcached", "mysql", "postgres", "redis" или "shm", или укажите имя пользовательского модуля ("custom-storage"), или table, реализующую интерфейс хранилища сессий. |
revocation |
nil |
Хранилище, используемое для записей об отзыве cookie-сессий. Используйте nil или false для отключения, имя хранилища, такое как "shm", "redis", "mysql" или "postgres", имя пользовательского модуля хранилища или table хранилища с методами set/get. |
revocation_fail_mode |
"open" |
Поведение, когда хранилище отзывов недоступно, используйте "open" (считать не отозванным) или "closed" (отклонить сессию). |
dshm |
nil |
Конфигурация для хранилища dshm, например, { prefix = "sessions" } (см. ниже) |
file |
nil |
Конфигурация для файлового хранилища, например, { path = "/tmp", suffix = "session" } (см. ниже) |
memcached |
nil |
Конфигурация для хранилища memcached, например, { prefix = "sessions" } (см. ниже) |
mysql |
nil |
Конфигурация для хранилища MySQL / MariaDB, например, { database = "sessions" } (см. ниже) |
postgres |
nil |
Конфигурация для хранилища Postgres, например, { database = "sessions" } (см. ниже) |
redis |
nil |
Конфигурация для хранилищ Redis / Redis Sentinel / Redis Cluster, например, { prefix = "sessions" } (см. ниже) |
shm |
nil |
Конфигурация для хранилища в разделяемой памяти, например, { zone = "sessions" } |
["custom-storage"] |
nil |
Конфигурация пользовательского хранилища (загружается с помощью require "custom-storage"). |
Конфигурация cookie-хранилища
При хранении данных в cookie не требуется дополнительная конфигурация,
просто установите storage в nil или "cookie".
Конфигурация отзыва сессии
Cookie-сессии (без сохранения состояния) являются самодостаточными: после выдачи cookie остается действительным до истечения срока действия в соответствии с настроенными таймаутами. Отзыв добавляет необязательный список отзыва на основе хранилища, чтобы уничтоженные сессии отклонялись немедленно, не дожидаясь истечения срока действия cookie.
Отзыв доступен только когда данные сессии хранятся в cookie
(storage равен nil или "cookie"). Выберите серверную часть явно с помощью
revocation = "dshm", "file", "memcached", "mysql", "postgres",
"redis" или "shm". Серверная часть использует свою обычную секцию конфигурации и
тот же контракт set/get хранилища, который используется для данных сессии. Пользовательские
имена модулей хранилища и предварительно созданные таблицы хранилища также поддерживаются. Установка
revocation = false или оставление его неустановленным отключает отзыв.
При каждом session:open библиотека проверяет, отозван ли идентификатор сессии.
При session:destroy идентификатор записывается в выбранное
хранилище с TTL, равным оставшемуся времени жизни сессии (скользящий и
абсолютный таймауты). Метка отзыва — это легковесный маркер; никакие данные
сессии не сохраняются.
Используйте revocation_fail_mode для управления поведением, когда хранилище недоступно:
"open"(по умолчанию): записать предупреждение и считать сессию не отозванной. Уничтожение все равно очищает cookie, даже если запись об отзыве не удалась."closed": отклонить операцию открытия или уничтожения сессии.
Отзыв применяется к session:destroy (и session:logout, когда он уничтожает
последнюю аудиторию). Он не отзывает предыдущий идентификатор сессии при
session:save (ротация сессии) или частичном session:logout (несколько
аудиторий). После ротации или частичного выхода из системы предыдущий cookie
остается пригодным для использования до истечения stale_ttl или таймаута.
Примеры:
-- Список отзыва в Redis
require("resty.session").init({
storage = "cookie",
revocation = "redis",
redis = {
host = "127.0.0.1",
password = "secret",
prefix = "sessions",
},
})
-- Список отзыва в разделяемой памяти
require("resty.session").init({
storage = "cookie",
revocation = "shm",
shm = {
zone = "sessions",
prefix = "revocations",
},
})
-- Список отзыва в MySQL
require("resty.session").init({
storage = "cookie",
revocation = "mysql",
mysql = {
host = "127.0.0.1",
database = "sessions",
username = "session",
password = "secret",
},
})
Тот же шаблон работает для "dshm", "file", "memcached" и "postgres".
Конфигурация DSHM-хранилища
С хранилищем DSHM вы можете использовать следующие настройки (установите storage в "dshm"):
| Параметр | По умолчанию | Описание |
|---|---|---|
prefix |
nil |
Префикс для ключей, хранящихся в DSHM. |
suffix |
nil |
Суффикс для ключей, хранящихся в DSHM. |
host |
"127.0.0.1" |
Хост для подключения. |
port |
4321 |
Порт для подключения. |
connect_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе connect объекта TCP/unix-доменного сокета. |
send_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе send объекта TCP/unix-доменного сокета. |
read_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе receive объекта TCP/unix-доменного сокета. |
keepalive_timeout |
nil |
Управляет максимальным временем простоя по умолчанию для соединений в пуле соединений. |
pool |
nil |
Пользовательское имя для используемого пула соединений. |
pool_size |
nil |
Размер пула соединений. |
backlog |
nil |
Размер очереди для использования, когда пул соединений заполнен (настраивается с помощью pool_size). |
ssl |
nil |
Включить SSL. |
ssl_verify |
nil |
Проверять сертификат сервера. |
server_name |
nil |
Имя сервера для нового расширения TLS Server Name Indication (SNI). |
Пожалуйста, обратитесь к ngx-distributed-shm, чтобы установить необходимые зависимости.
Конфигурация файлового хранилища
С файловым хранилищем вы можете использовать следующие настройки (установите storage в "file"):
| Параметр | По умолчанию | Описание |
|---|---|---|
prefix |
nil |
Префикс файла для файла сессии. |
suffix |
nil |
Суффикс файла (или расширение без .) для файла сессии. |
pool |
nil |
Имя пула потоков, в котором происходит запись файла (доступно только на Linux). |
path |
(временная директория) | Путь (или директория), в которой создаются файлы сессий. |
Реализация требует LuaFileSystem, который вы можете установить с помощью LuaRocks:
❯ luarocks install LuaFileSystem
Конфигурация Memcached-хранилища
С Memcached вы можете использовать следующие настройки (установите storage в "memcached"):
| Параметр | По умолчанию | Описание |
|---|---|---|
prefix |
nil |
Префикс для ключей, хранящихся в memcached. |
suffix |
nil |
Суффикс для ключей, хранящихся в memcached. |
host |
127.0.0.1 |
Хост для подключения. |
port |
11211 |
Порт для подключения. |
socket |
nil |
Файл сокета для подключения. |
connect_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе connect объекта TCP/unix-доменного сокета. |
send_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе send объекта TCP/unix-доменного сокета. |
read_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе receive объекта TCP/unix-доменного сокета. |
keepalive_timeout |
nil |
Управляет максимальным временем простоя по умолчанию для соединений в пуле соединений. |
pool |
nil |
Пользовательское имя для используемого пула соединений. |
pool_size |
nil |
Размер пула соединений. |
backlog |
nil |
Размер очереди для использования, когда пул соединений заполнен (настраивается с помощью pool_size). |
ssl |
false |
Включить SSL |
ssl_verify |
nil |
Проверять сертификат сервера |
server_name |
nil |
Имя сервера для нового расширения TLS Server Name Indication (SNI). |
Конфигурация MySQL / MariaDB-хранилища
С MySQL / MariaDB вы можете использовать следующие настройки (установите storage в "mysql"):
| Параметр | По умолчанию | Описание |
|---|---|---|
host |
"127.0.0.1" |
Хост для подключения. |
port |
3306 |
Порт для подключения. |
socket |
nil |
Файл сокета для подключения. |
username |
nil |
Имя пользователя базы данных для аутентификации. |
password |
nil |
Пароль для аутентификации, может потребоваться в зависимости от конфигурации сервера. |
charset |
"ascii" |
Набор символов, используемый в соединении MySQL. |
database |
nil |
Имя базы данных для подключения. |
table_name |
"sessions" |
Имя таблицы базы данных, в которой хранятся данные сессии. |
table_name_meta |
"sessions_meta" |
Имя таблицы метаданных базы данных, в которой хранятся метаданные сессии. |
max_packet_size |
1048576 |
Верхний предел для пакетов ответа, отправляемых с сервера MySQL (в байтах). |
connect_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе connect объекта TCP/unix-доменного сокета. |
send_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе send объекта TCP/unix-доменного сокета. |
read_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе receive объекта TCP/unix-доменного сокета. |
keepalive_timeout |
nil |
Управляет максимальным временем простоя по умолчанию для соединений в пуле соединений. |
pool |
nil |
Пользовательское имя для используемого пула соединений. |
pool_size |
nil |
Размер пула соединений. |
backlog |
nil |
Размер очереди для использования, когда пул соединений заполнен (настраивается с помощью pool_size). |
ssl |
false |
Включить SSL. |
ssl_verify |
nil |
Проверять сертификат сервера. |
Вам также необходимо создать следующие таблицы в вашей базе данных:
--
-- Таблица базы данных, которая хранит данные сессии.
--
CREATE TABLE IF NOT EXISTS sessions (
sid CHAR(43) PRIMARY KEY,
name VARCHAR(255),
data MEDIUMTEXT,
exp DATETIME,
INDEX (exp)
) CHARACTER SET ascii;
--
-- Таблица метаданных сессий.
--
-- Это необходимо только если вы хотите хранить метаданные сессий.
--
CREATE TABLE IF NOT EXISTS sessions_meta (
aud VARCHAR(255),
sub VARCHAR(255),
sid CHAR(43),
PRIMARY KEY (aud, sub, sid),
CONSTRAINT FOREIGN KEY (sid) REFERENCES sessions(sid) ON DELETE CASCADE ON UPDATE CASCADE
) CHARACTER SET ascii;
Конфигурация Postgres
С Postgres вы можете использовать следующие настройки (установите storage в "postgres"):
| Параметр | По умолчанию | Описание |
|---|---|---|
host |
"127.0.0.1" |
Хост для подключения. |
port |
5432 |
Порт для подключения. |
application |
5432 |
Установить имя соединения, отображаемое в pg_stat_activity (по умолчанию "pgmoon"). |
username |
"postgres" |
Имя пользователя базы данных для аутентификации. |
password |
nil |
Пароль для аутентификации, может потребоваться в зависимости от конфигурации сервера. |
database |
nil |
Имя базы данных для подключения. |
table_name |
"sessions" |
Имя таблицы базы данных, в которой хранятся данные сессии (может быть с префиксом схема базы данных). |
table_name_meta |
"sessions_meta" |
Имя таблицы метаданных базы данных, в которой хранятся метаданные сессии (может быть с префиксом схема базы данных). |
connect_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе connect объекта TCP/unix-доменного сокета. |
send_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе send объекта TCP/unix-доменного сокета. |
read_timeout |
nil |
Управляет значением таймаута по умолчанию, используемым в методе receive объекта TCP/unix-доменного сокета. |
keepalive_timeout |
nil |
Управляет максимальным временем простоя по умолчанию для соединений в пуле соединений. |
pool |
nil |
Пользовательское имя для используемого пула соединений. |
pool_size |
nil |
Размер пула соединений |