A classe SessionHandler

(PHP 5 >= 5.4.0, PHP 7, PHP 8)

Introdução

SessionHandler é uma classe especial que pode ser usada para expor o manipulador interno atual do PHP de gravação de sessão por herança. Existem sete métodos que envolvem (wrap) as sete funções internas de callbacks do manipulador de gravação de sessão (open, close, read, write, destroy, gc e create_sid). Por padrão, esta classe vai envolver qualquer manipulador de gravação interno definido pela diretiva de configuração session.save_handler, que normalmente é files por padrão. Outros manipuladores internos de gravação de sessão podem ser fornecidos por extensões do PHP, como por exemplo SQLite (como sqlite), Memcache (como memcache), e Memcached (como memcached).

Quando uma instância de SessionHandler é definida como manipulador de gravação usando session_set_save_handler(), ela envolverá o manipulador de gravação atual. Uma classe que estende SessionHandler permite sobrescrever os métodos, interceptá-los ou filtrá-los chamando os métodos da classe pai que envolvem os manipuladores de sessão internos do PHP.

Isto permite, por exemplo, interceptar os métodos read e write para criptografar/descriptografar os dados de sessão e então passar o resultado de e para a classe pai. Alternativamente, pode-se sobrescrever completamente um método como o callback de limpeza gc.

Como o SessionHandler envolve os manipuladores de gravação atuais, o exemplo acima de criptografia pode ser aplicado em qualquer manipulador de gravação interno sem precisar saber o funcionamento interno dos manipuladores.

Para usar esta classe, primeiro configure o manipulador de gravação que você quer expor usando session.save_handler e então passe uma instância de SessionHandler ou uma classe que a estenda para session_set_save_handler().

Note que os métodos de callbacks desta classe são projetados para serem chamados internamente pelo PHP e não para serem chamados pelo código do usuário. Os valores de retorno são igualmente processados internamente pelo PHP. Para mais informações do fluxo de trabalho da sessão, consulte session_set_save_handler().

Resumo da classe

class SessionHandler implements SessionHandlerInterface, SessionIdInterface {
/* Métodos */
public close(): bool
public create_sid(): string
public destroy(string $id): bool
public gc(int $max_lifetime): int|false
public open(string $path, string $name): bool
public read(string $id): string|false
public write(string $id, string $data): bool
}

Notas

Warning

Esta classe é projetada para expor o manipulador interno do PHP de gravação de sessão; se você quiser escrever manipuladores de gravação personalizados, implemente a interface SessionHandlerInterface ao invés de estender a classe SessionHandler.

Exemplos

Example #1 Usando SessionHandler para adicionar criptografia aos manipuladores internos do PHP de gravação.

<?php

 /**
  * decrypt AES 256
  *
  * @param data $edata
  * @param string $password
  * @return decrypted data
  */
function decrypt($edata, $password) {
    $data = base64_decode($edata);
    $salt = substr($data, 0, 16);
    $ct = substr($data, 16);

    $rounds = 3; // depende do comprimento da chave
    $data00 = $password.$salt;
    $hash = array();
    $hash[0] = hash('sha256', $data00, true);
    $result = $hash[0];
    for ($i = 1; $i < $rounds; $i++) {
        $hash[$i] = hash('sha256', $hash[$i - 1].$data00, true);
        $result .= $hash[$i];
    }
    $key = substr($result, 0, 32);
    $iv  = substr($result, 32,16);

    return openssl_decrypt($ct, 'AES-256-CBC', $key, true, $iv);
  }

/**
 * crypt AES 256
 *
 * @param data $data
 * @param string $password
 * @return base64 encrypted data
 */
function encrypt($data, $password) {
    // Gera um salt aleatório criptograficamente seguro usando random_bytes()
    $salt = random_bytes(16);

    $salted = '';
    $dx = '';
    // Salt em key(32) e iv(16) = 48
    while (strlen($salted) < 48) {
        $dx = hash('sha256', $dx.$password.$salt, true);
        $salted .= $dx;
    }

    $key = substr($salted, 0, 32);
    $iv  = substr($salted, 32,16);

    $encrypted_data = openssl_encrypt($data, 'AES-256-CBC', $key, true, $iv);
    return base64_encode($salt . $encrypted_data);
}

class EncryptedSessionHandler extends SessionHandler
{
    private $key;

    public function __construct($key)
    {
        $this->key = $key;
    }

    public function read($id)
    {
        $data = parent::read($id);

        if (!$data) {
            return "";
        } else {
            return decrypt($data, $this->key);
        }
    }

    public function write($id, $data)
    {
        $data = encrypt($data, $this->key);

        return parent::write($id, $data);
    }
}

// iremos interceptar o manipulador nativo de arquivos, mas trabalharemos igualmente
// com outros manipuladores internos como 'sqlite', 'memcache' ou 'memcached'
// que são disponibilizados por extensões do PHP
ini_set('session.save_handler', 'files');

$key = 'secret_string';
$handler = new EncryptedSessionHandler($key);
session_set_save_handler($handler, true);
session_start();

// proceder para definir e recuperar os valores pela chave de $_SESSION

Note:

Como os métodos dessa classe são projetados para serem chamados internamente pelo PHP como parte do fluxo normal da sessão, chamadas à esses métodos (ou seja, os manipuladores internos nativos reais) por classes filhas irão retornar false, a não ser que a sessão tenha sido iniciada (independente se foi de forma automática ou pela chamada de session_start()). É importante levar isto em consideração quando escrever testes unitários onde os métodos da classe podem ser invocados manualmente.

Table of Contents