Pular para conteúdo

session: Biblioteca de sessão para nginx-module-lua – flexível e segura

Instalação

Se você ainda não configurou a assinatura do repositório RPM, cadastre-se. Em seguida, você pode prosseguir com os seguintes passos.

CentOS/RHEL 7 ou 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

Para usar esta biblioteca Lua com NGINX, certifique-se de que o nginx-module-lua esteja instalado.

Este documento descreve o lua-resty-session v4.2.0 lançado em 24 de agosto de 2026.


lua-resty-session é uma biblioteca de sessão segura e flexível para OpenResty.

Resumo;

  • As sessões são imutáveis (cada salvamento gera uma nova sessão) e sem bloqueio.
  • Os dados da sessão são criptografados com AES-256-GCM usando uma chave derivada com HKDF-SHA256 (no modo FIPS, usa PBKDF2 com SHA-256).
  • A sessão tem um cabeçalho de tamanho fixo protegido com HMAC-SHA256 MAC com uma chave derivada usando HKDF-SHA256 (no modo FIPS, usa PBKDF2 com SHA-256).
  • Os dados da sessão podem ser armazenados em um cookie sem estado ou em vários armazenamentos de backend.
  • Um único cookie de sessão pode manter várias sessões em diferentes públicos.

Nota: A versão 4.0.0 foi uma reescrita desta biblioteca com muitas lições aprendidas durante os anos. Se você ainda usa uma versão mais antiga, consulte a documentação antiga.

Sinopse

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>Iniciar o teste</a>
          </body>
          </html>
        ]])
      }
    }

    location /start {
      content_by_lua_block {
        local session = require "resty.session".new()
        session:set_subject("Fã do OpenResty")
        session:set("quote", "A rápida raposa marrom pula sobre o cão preguiçoso")
        local ok, err = session:save()

        ngx.say(string.format([[
          <html>
          <body>
            <p>Sessão iniciada (%s)</p>
            <p><a href=/started>Verificar se realmente foi</a></p>
          </body>
          </html>
        ]], err or "sem erro"))
      }
    }

    location /started {
      content_by_lua_block {
        local session, err = require "resty.session".start()

        ngx.say(string.format([[
          <html>
          <body>
            <p>Sessão foi iniciada por %s (%s)</p>
            <p><blockquote>%s</blockquote></p>
            <p><a href=/modify>Modificar a sessão</a></p>
          </body>
          </html>
        ]],
          session:get_subject() or "Anônimo",
          err or "sem erro",
          session:get("quote") or "sem citação"
        ))
      }
    }

    location /modify {
      content_by_lua_block {
        local session, err = require "resty.session".start()
        session:set_subject("Fã de Lua")
        session:set("quote", "Lorem ipsum dolor sit amet")
        local _, err_save = session:save()

        ngx.say(string.format([[
          <html>
          <body>
            <p>Sessão foi modificada (%s)</p>
            <p><a href=/modified>Verificar se está modificada</a></p>
          </body>
          </html>
        ]], err or err_save or "sem erro"))
      }
    }

    location /modified {
      content_by_lua_block {
        local session, err = require "resty.session".start()

        ngx.say(string.format([[
          <html>
          <body>
            <p>Sessão foi iniciada por %s (%s)</p>
            <p><blockquote>%s</blockquote></p>
            <p><a href=/destroy>Destruir a sessão</a></p>
          </body>
          </html>
        ]],
          session:get_subject() or "Anônimo",
          err or "sem erro",
          session:get("quote")  or "sem citação"
        ))
      }
    }

    location /destroy {
      content_by_lua_block {
        local ok, err = require "resty.session".destroy()

        ngx.say(string.format([[
          <html>
          <body>
            <p>Sessão foi destruída (%s)</p>
            <p><a href=/destroyed>Verificar se realmente foi?</a></p>
          </body>
          </html>
        ]], err or "sem erro"))
      }
    }

    location /destroyed {
      content_by_lua_block {
        local session, err = require "resty.session".open()

        ngx.say(string.format([[
          <html>
          <body>
            <p>A sessão foi realmente destruída, você é conhecido como %s (%s)</p>
            <p><a href=/>Começar novamente</a></p>
          </body>
          </html>
        ]],
          session:get_subject() or "Anônimo",
          err or "sem erro"
        ))
      }
    }
  }
}

Configuração

A configuração pode ser dividida em configuração genérica de sessão e configuração de armazenamento no lado do servidor.

Aqui está um exemplo:

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",
    },
  })
}

Configuração da Sessão

A configuração da sessão pode ser passada para funções de inicialização, construtores, e auxiliares.

Aqui estão as opções de configuração de sessão possíveis:

Opção Padrão Descrição
secret nil Segredo usado para a derivação de chave. O segredo é submetido a hash com SHA-256 antes de ser usado. Ex.: "RaJKp8UQW1".
secret_fallbacks nil Matriz de segredos que podem ser usados como segredos alternativos (ao fazer rotação de chaves), Ex.: { "6RfrAYYzYq", "MkbTkkyF9C" }.
ikm (aleatório) O material de chaveamento inicial (ou ikm) pode ser especificado diretamente (sem usar um segredo) com exatamente 32 bytes de dados. Ex.: "5ixIW4QVMk0dPtoIhn41Eh1I9enP2060"
ikm_fallbacks nil Matriz de materiais de chaveamento iniciais que podem ser usados como chaves alternativas (ao fazer rotação de chaves), Ex.: { "QvPtlPKxOKdP5MCu1oI3lOEXIVuDckp7" }.
cookie_prefix nil Prefixo do cookie, use nil, "__Host-" ou "__Secure-".
cookie_name "session" Nome do cookie de sessão, ex.: "session".
cookie_path "/" Caminho do cookie, ex.: "/".
cookie_domain nil Domínio do cookie, ex.: "example.com"
cookie_http_only true Marcar cookie como somente HTTP, use true ou false.
cookie_secure nil Marcar cookie como seguro, use nil, true ou false.
cookie_priority nil Prioridade do cookie, use nil, "Low", "Medium" ou "High".
cookie_same_site "Lax" Política de mesmo site do cookie, use nil, "Lax", "Strict", "None" ou "Default"
cookie_same_party nil Marcar cookie com sinalizador de mesma parte, use nil, true ou false.
cookie_partitioned nil Marcar cookie com sinalizador de particionado, use nil, true ou false.
remember false Ativar ou desativar sessões persistentes, use nil, true ou false.
remember_safety "Medium" Complexidade da derivação de chave do cookie de lembrar, use nil, "None" (rápido), "Low", "Medium", "High" ou "Very High" (lento).
remember_cookie_name "remember" Nome do cookie de sessão persistente, ex.: "remember".
audience "default" Público da sessão, ex.: "my-application".
subject nil Assunto da sessão, ex.: "[email protected]".
enforce_same_subject false Quando definido como true, os públicos precisam compartilhar o mesmo assunto. A biblioteca remove dados de público que não correspondem ao assunto ao salvar.
stale_ttl 10 Quando a sessão é salva, uma nova sessão é criada; o stale ttl especifica por quanto tempo a antiga ainda pode ser usada, ex.: 10 (em segundos).
idling_timeout 900 O tempo limite de inatividade especifica por quanto tempo a sessão pode ficar inativa até ser considerada inválida, ex.: 900 (15 minutos) (em segundos), 0 desativa as verificações e o toque.
rolling_timeout 3600 O tempo limite contínuo especifica por quanto tempo a sessão pode ser usada até precisar ser renovada, ex.: 3600 (uma hora) (em segundos), 0 desativa as verificações e a renovação contínua.
absolute_timeout 86400 O tempo limite absoluto limita por quanto tempo a sessão pode ser renovada, até que a reautenticação seja necessária, ex.: 86400 (um dia) (em segundos), 0 desativa as verificações.
remember_rolling_timeout 604800 O tempo limite de lembrar especifica por quanto tempo a sessão persistente é considerada válida, ex.: 604800 (uma semana) (em segundos), 0 desativa as verificações e a renovação contínua.
remember_absolute_timeout 2592000 O tempo limite absoluto de lembrar limita por quanto tempo a sessão persistente pode ser renovada, até que a reautenticação seja necessária, ex.: 2592000 (30 dias) (em segundos), 0 desativa as verificações.
hash_storage_key false Se deve ou não aplicar hash à chave de armazenamento. Com a chave de armazenamento com hash, é impossível descriptografar dados no lado do servidor sem ter também um cookie, use nil, true ou false.
hash_subject false Se deve ou não aplicar hash ao assunto quando store_metadata está ativado, ex.: por motivos de PII.
store_metadata false Se também deve armazenar metadados de sessões, como coletar dados de sessões para um público específico pertencente a um assunto específico.
touch_threshold 60 O limite de toque controla com que frequência ou infrequência o session:refresh toca o cookie, ex.: 60 (um minuto) (em segundos)
compression_threshold 1024 O limite de compressão controla quando os dados são deflacionados, ex.: 1024 (um quilobyte) (em bytes), 0 desativa a compressão.
bind nil Vincule a sessão a dados adquiridos da solicitação HTTP ou conexão, use ip, scheme, user-agent. Ex.: { "scheme", "user-agent" } calculará o MAC utilizando também o Scheme da solicitação HTTP e o cabeçalho User-Agent.
request_headers nil Conjunto de cabeçalhos para enviar ao upstream, use id, audience, subject, timeout, idling-timeout, rolling-timeout, absolute-timeout. Ex.: { "id", "timeout" } definirá os cabeçalhos de solicitação Session-Id e Session-Timeout quando set_headers for chamado.
response_headers nil Conjunto de cabeçalhos para enviar ao downstream, use id, audience, subject, timeout, idling-timeout, rolling-timeout, absolute-timeout. Ex.: { "id", "timeout" } definirá os cabeçalhos de resposta Session-Id e Session-Timeout quando set_headers for chamado.
storage nil O armazenamento é responsável por armazenar os dados da sessão, use nil ou "cookie" (os dados são armazenados no cookie), "dshm", "file", "memcached", "mysql", "postgres", "redis" ou "shm", ou forneça um nome de módulo personalizado ("custom-storage"), ou uma table que implemente a interface de armazenamento de sessão.
revocation nil Armazenamento usado para registros de revogação de sessão de cookie. Use nil ou false para desativar, um nome de armazenamento como "shm", "redis", "mysql" ou "postgres", um nome de módulo de armazenamento personalizado ou uma table de armazenamento com métodos set/get.
revocation_fail_mode "open" Comportamento quando o armazenamento de revogação está inacessível, use "open" (tratar como não revogado) ou "closed" (rejeitar a sessão).
dshm nil Configuração para armazenamento dshm, ex.: { prefix = "sessions" } (veja abaixo)
file nil Configuração para armazenamento de arquivo, ex.: { path = "/tmp", suffix = "session" } (veja abaixo)
memcached nil Configuração para armazenamento memcached, ex.: { prefix = "sessions" } (veja abaixo)
mysql nil Configuração para armazenamento MySQL / MariaDB, ex.: { database = "sessions" } (veja abaixo)
postgres nil Configuração para armazenamento Postgres, ex.: { database = "sessions" } (veja abaixo)
redis nil Configuração para armazenamentos Redis / Redis Sentinel / Redis Cluster, ex.: { prefix = "sessions" } (veja abaixo)
shm nil Configuração para armazenamento de memória compartilhada, ex.: { zone = "sessions" }
["custom-storage"] nil Configuração de armazenamento personalizado (carregado com require "custom-storage").

Ao armazenar dados em cookie, nenhuma configuração adicional é necessária; basta definir o storage como nil ou "cookie".

Configuração de Revogação de Sessão

Sessões de cookie (sem estado) são autocontidas: uma vez emitidas, um cookie permanece válido até expirar de acordo com os tempos limite configurados. A revogação adiciona uma lista de negação opcional baseada em armazenamento para que sessões destruídas sejam rejeitadas imediatamente, sem esperar a expiração do cookie.

A revogação só está disponível quando os dados da sessão são armazenados no cookie (storage é nil ou "cookie"). Selecione o backend explicitamente com revocation = "dshm", "file", "memcached", "mysql", "postgres", "redis" ou "shm". O backend usa sua seção de configuração normal e o mesmo contrato de armazenamento set/get usado para dados de sessão. Nomes de módulos de armazenamento personalizados e tabelas de armazenamento pré-construídas também são suportados. Definir revocation = false ou deixá-lo não definido desativa a revogação.

Em cada session:open, a biblioteca verifica se o identificador da sessão está revogado. Em session:destroy, o identificador é gravado no armazenamento selecionado com um TTL igual ao tempo de vida restante da sessão (tempos limite contínuo e absoluto). A marca de revogação é um sentinela leve; nenhum payload de sessão é armazenado.

Use revocation_fail_mode para controlar o comportamento quando o armazenamento está indisponível:

  • "open" (padrão): registra um aviso e trata a sessão como não revogada. A destruição ainda limpa o cookie mesmo se a gravação de revogação falhar.
  • "closed": rejeita a operação de abertura ou destruição da sessão.

A revogação se aplica a session:destroy (e session:logout quando destrói o último público). Ela não revoga o identificador de sessão anterior em session:save (rotação de sessão) ou session:logout parcial (múltiplos públicos). Após rotação ou logout parcial, o cookie anterior permanece utilizável até que seu stale_ttl ou tempo limite expire.

Exemplos:

-- Lista de negação Redis
require("resty.session").init({
  storage = "cookie",
  revocation = "redis",
  redis = {
    host = "127.0.0.1",
    password = "secret",
    prefix = "sessions",
  },
})

-- Lista de negação de memória compartilhada
require("resty.session").init({
  storage = "cookie",
  revocation = "shm",
  shm = {
    zone = "sessions",
    prefix = "revocations",
  },
})

-- Lista de negação MySQL
require("resty.session").init({
  storage = "cookie",
  revocation = "mysql",
  mysql = {
    host = "127.0.0.1",
    database = "sessions",
    username = "session",
    password = "secret",
  },
})

O mesmo padrão funciona para "dshm", "file", "memcached" e "postgres".

Configuração de Armazenamento DSHM

Com o armazenamento DHSM, você pode usar as seguintes configurações (defina o storage como "dshm"):

Opção Padrão Descrição
prefix nil O prefixo para as chaves armazenadas no DSHM.
suffix nil O sufixo para as chaves armazenadas no DSHM.
host "127.0.0.1" O host para conectar.
port 4321 A porta para conectar.
connect_timeout nil Controla o valor de tempo limite padrão usado no método connect do objeto de socket TCP/domínio unix.
send_timeout nil Controla o valor de tempo limite padrão usado no método send do objeto de socket TCP/domínio unix.
read_timeout nil Controla o valor de tempo limite padrão usado no método receive do objeto de socket TCP/domínio unix.
keepalive_timeout nil Controla o tempo máximo de inatividade padrão das conexões no pool de conexões.
pool nil Um nome personalizado para o pool de conexões usado.
pool_size nil O tamanho do pool de conexões.
backlog nil Um tamanho de fila a ser usado quando o pool de conexões está cheio (configurado com pool_size).
ssl nil Ativar SSL.
ssl_verify nil Verificar certificado do servidor.
server_name nil O nome do servidor para a nova extensão TLS Server Name Indication (SNI).

Consulte ngx-distributed-shm para obter as dependências necessárias instaladas.

Configuração de Armazenamento de Arquivo

Com o armazenamento de arquivo, você pode usar as seguintes configurações (defina o storage como "file"):

Opção Padrão Descrição
prefix nil Prefixo do arquivo para o arquivo de sessão.
suffix nil Sufixo do arquivo (ou extensão sem .) para o arquivo de sessão.
pool nil Nome do pool de threads sob o qual a gravação de arquivo acontece (disponível apenas no Linux).
path (diretório tmp) Caminho (ou diretório) sob o qual os arquivos de sessão são criados.

A implementação requer LuaFileSystem que você pode instalar com LuaRocks:

 luarocks install LuaFileSystem

Configuração de Armazenamento Memcached

Com o Memcached de arquivo, você pode usar as seguintes configurações (defina o storage como "memcached"):

Opção Padrão Descrição
prefix nil Prefixo para as chaves armazenadas no memcached.
suffix nil Sufixo para as chaves armazenadas no memcached.
host 127.0.0.1 O host para conectar.
port 11211 A porta para conectar.
socket nil O arquivo de socket para conectar.
connect_timeout nil Controla o valor de tempo limite padrão usado no método connect do objeto de socket TCP/domínio unix.
send_timeout nil Controla o valor de tempo limite padrão usado no método send do objeto de socket TCP/domínio unix.
read_timeout nil Controla o valor de tempo limite padrão usado no método receive do objeto de socket TCP/domínio unix.
keepalive_timeout nil Controla o tempo máximo de inatividade padrão das conexões no pool de conexões.
pool nil Um nome personalizado para o pool de conexões usado.
pool_size nil O tamanho do pool de conexões.
backlog nil Um tamanho de fila a ser usado quando o pool de conexões está cheio (configurado com pool_size).
ssl false Ativar SSL
ssl_verify nil Verificar certificado do servidor
server_name nil O nome do servidor para a nova extensão TLS Server Name Indication (SNI).

Configuração de Armazenamento MySQL / MariaDB

Com o MySQL / MariaDB de arquivo, você pode usar as seguintes configurações (defina o storage como "mysql"):

Opção Padrão Descrição
host "127.0.0.1" O host para conectar.
port 3306 A porta para conectar.
socket nil O arquivo de socket para conectar.
username nil O nome de usuário do banco de dados para autenticar.
password nil Senha para autenticação, pode ser necessária dependendo da configuração do servidor.
charset "ascii" O conjunto de caracteres usado na conexão MySQL.
database nil O nome do banco de dados para conectar.
table_name "sessions" Nome da tabela do banco de dados na qual armazenar os dados da sessão.
table_name_meta "sessions_meta" Nome da tabela de metadados do banco de dados na qual armazenar os metadados da sessão.
max_packet_size 1048576 O limite superior para os pacotes de resposta enviados pelo servidor MySQL (em bytes).
connect_timeout nil Controla o valor de tempo limite padrão usado no método connect do objeto de socket TCP/domínio unix.
send_timeout nil Controla o valor de tempo limite padrão usado no método send do objeto de socket TCP/domínio unix.
read_timeout nil Controla o valor de tempo limite padrão usado no método receive do objeto de socket TCP/domínio unix.
keepalive_timeout nil Controla o tempo máximo de inatividade padrão das conexões no pool de conexões.
pool nil Um nome personalizado para o pool de conexões usado.
pool_size nil O tamanho do pool de conexões.
backlog nil Um tamanho de fila a ser usado quando o pool de conexões está cheio (configurado com pool_size).
ssl false Ativar SSL.
ssl_verify nil Verificar certificado do servidor.

Você também precisa criar as seguintes tabelas em seu banco de dados:

--
-- Tabela do banco de dados que armazena os dados da sessão.
--
CREATE TABLE IF NOT EXISTS sessions (
  sid  CHAR(43) PRIMARY KEY,
  name VARCHAR(255),
  data MEDIUMTEXT,
  exp  DATETIME,
  INDEX (exp)
) CHARACTER SET ascii;

--
-- Tabela de metadados de sessões.
--
-- Isso só é necessário se você quiser armazenar metadados de sessão.
--
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;

Configuração do Postgres

Com o Postgres de arquivo, você pode usar as seguintes configurações (defina o storage como "postgres"):

Opção Padrão Descrição
host "127.0.0.1" O host para conectar.
port 5432 A porta para conectar.
application 5432 Define o nome da conexão como exibido em pg_stat_activity (padrão é "pgmoon").
username "postgres" O nome de usuário do banco de dados para autenticar.
password nil Senha para autenticação, pode ser necessária dependendo da configuração do servidor.
database nil O nome do banco de dados para conectar.
table_name "sessions" Nome da tabela do banco de dados na qual armazenar os dados da sessão (pode ser prefixado com esquema do banco de dados).
table_name_meta "sessions_meta" Nome da tabela de metadados do banco de dados na qual armazenar os metadados da sessão (pode ser prefixado com esquema do banco de dados).
connect_timeout nil Controla o valor de tempo limite padrão usado no método connect do objeto de socket TCP/domínio unix.
send_timeout nil Controla o valor de tempo limite padrão usado no método send do objeto de socket TCP/domínio unix.
read_timeout nil Controla o valor de tempo limite padrão usado no método receive do objeto de socket TCP/domínio unix.
keepalive_timeout nil Controla o tempo máximo de inatividade padrão das conexões no pool de conexões.
pool nil Um nome personalizado para o pool de conexões usado.
pool_size nil O tamanho do pool de conexões.
backlog nil Um tamanho de fila a ser usado quando o pool de conexões está cheio (configurado com pool_size).
ssl false Ativar SSL.
ssl_verify nil Verificar certificado do servidor.
ssl_required nil Abortar a conexão se o servidor não suportar conexões SSL.

Você também precisa criar as seguintes tabelas em seu banco