세션 처리 SessionHandler 클래스

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


소개

SessionHandler는 상속을 통해 현재 내부 PHP 세션 저장 핸들러를 노출하는 데 사용할 수 있는 특수 클래스입니다. 7개의 내부 세션 저장 핸들러 콜백(open, close, read, write, destroy, gccreate_sid)을 래핑하는 7개의 메소드가 있습니다. 기본적으로 이 클래스는 일반적으로 기본적으로 filessession.save_handler 구성 지시문에 의해 정의된 대로 내부 저장 핸들러가 설정되는 모든 것을 래핑합니다. 다른 내부 세션 저장 핸들러는 SQLite(sqlite), Memcache(memcache) 및 Memcached(memcached)와 같은 PHP 확장에서 제공됩니다.

SessionHandler의 일반 인스턴스가 session_set_save_handler()를 사용하여 저장 핸들러로 설정되면 현재 저장 핸들러를 래핑합니다. SessionHandler에서 확장된 클래스를 사용하면 메서드를 재정의하거나 궁극적으로 내부 PHP 세션 핸들러를 래핑하는 상위 클래스 메서드를 호출하여 메서드를 가로채거나 필터링할 수 있습니다.

이를 통해 예를 들어 readwrite 메서드를 가로채서 세션 데이터를 암호화/복호화한 다음 부모 클래스와 결과를 주고받을 수 있습니다. 또는 가비지 컬렉션 콜백 gc와 같은 메서드를 완전히 재정의하도록 선택할 수도 있습니다.

SessionHandler는 현재 내부 저장 핸들러 메소드를 래핑하기 때문에 위의 암호화 예제는 핸들러의 내부를 몰라도 모든 내부 저장 핸들러에 적용할 수 있습니다.

이 클래스를 사용하려면 먼저 session.save_handler를 사용하여 노출하려는 저장 핸들러를 설정한 다음 SessionHandler 또는 이를 확장하는 인스턴스를 session_set_save_handler()로 전달합니다.

이 클래스의 콜백 메서드는 PHP에서 내부적으로 호출하도록 설계되었으며 사용자 공간 코드에서 호출할 수 없습니다. 반환 값은 PHP에서 내부적으로 동일하게 처리됩니다. 세션 워크플로에 대한 자세한 내용은 session_set_save_handler()를 참조하십시오.


클래스 개요

                  
class SessionHandler implements SessionHandlerInterface, SessionIdInterface {
  /* Methods */
  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
}
                  
                

경고 이 클래스는 현재 내부 PHP 세션 저장 핸들러를 노출하도록 설계되었습니다. 사용자 정의 저장 핸들러를 작성하려면 SessionHandler에서 확장하는 대신 SessionHandlerInterface 인터페이스를 구현하십시오.

예제 #1 SessionHandler를 사용하여 내부 PHP 저장 핸들러에 암호화를 추가합니다.

                  
<?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; // depends on key length
    $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) {
    // Set a random salt
    $salt = openssl_random_pseudo_bytes(16);

    $salted = '';
    $dx = '';
    // Salt the key(32) and 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);
    }
}

// we'll intercept the native 'files' handler, but will equally work
// with other internal native handlers like 'sqlite', 'memcache' or 'memcached'
// which are provided by PHP extensions.
ini_set('session.save_handler', 'files');

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

// proceed to set and retrieve values by key from $_SESSION
                  
                
메모:

이 클래스의 메서드는 일반 세션 워크플로의 일부로 PHP에서 내부적으로 호출하도록 설계되었으므로 세션이 실제로 시작되지 않은 경우(자동으로 또는 명시적 session_start()에 의해) 부모 메서드(즉, 실제 내부 네이티브 핸들러)에 대한 자식 클래스 호출은 false를 반환합니다. 이것은 클래스 메소드가 수동으로 호출될 수 있는 단위 테스트를 작성할 때 고려하는 것이 중요합니다.


목차