SessionHandlerInterface クラス
(PHP 5 >= 5.4.0, PHP 7, PHP 8)
はじめに
SessionHandlerInterface は カスタムセッションハンドラを作成する際の最低限のプロトタイプを定義したインターフェイスです。 自作のセッションハンドラを オブジェクト指向型 の起動方法で session_set_save_handler() に渡すために、このインターフェイスを実装することができます。
このクラスのコールバックメソッドは PHP が内部的にコールするものであり、 ユーザーのコードから呼ばれることは想定していないことに注意しましょう。
インターフェイス概要
例
例1 SessionHandlerInterface の使用例
この例では、ファイルベースのセッションストレージをつくります。これは
PHP のデフォルトのセッション保存ハンドラである files
と似たものです。この例をさらに拡張すれば、
PHP がサポートするお好みのデータベースを使ってセッションを保存させるようにするのも簡単です。
session_set_save_handler() でオブジェクト指向型のプロトタイプを使っていることと、 シャットダウン関数をその parameter フラグで登録していることに注目しましょう。 オブジェクトをセッション保存ハンドラとして使うときには、この方法をおすすめします。
コードを簡潔にするため、以下の例では入力値の検証を省略しています。
しかし、$id
パラメータは
パストラバーサル問題のような脆弱性を避けるために、
適切な 検証/無害化 が必須になる値です。
よって、ここで示した例を改変することなく、
本番の実環境で用いないでください
<?php
class MySessionHandler implements SessionHandlerInterface
{
private $savePath;
public function open($savePath, $sessionName): bool
{
$this->savePath = $savePath;
if (!is_dir($this->savePath)) {
mkdir($this->savePath, 0777);
}
return true;
}
public function close(): bool
{
return true;
}
#[\ReturnTypeWillChange]
public function read($id)
{
return (string) @file_get_contents("$this->savePath/sess_$id");
}
public function write($id, $data): bool
{
return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
}
public function destroy($id): bool
{
$file = "$this->savePath/sess_$id";
if (file_exists($file)) {
unlink($file);
}
return true;
}
#[\ReturnTypeWillChange]
public function gc($maxlifetime)
{
foreach (glob("$this->savePath/sess_*") as $file) {
if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
unlink($file);
}
}
return true;
}
}
$handler = new MySessionHandler();
session_set_save_handler($handler, true);
session_start();
// $_SESSION への値の設定や格納されている値の取得を進めます
目次
- SessionHandlerInterface::close — セッションを閉じる
- SessionHandlerInterface::destroy — セッションを破棄する
- SessionHandlerInterface::gc — 古いセッションを削除する
- SessionHandlerInterface::open — セッションを開始する
- SessionHandlerInterface::read — セッションのデータを読み込む
- SessionHandlerInterface::write — セッションのデータを書き込む
User Contributed Notes 8 notes
As of PHP 7.0, you can implement SessionUpdateTimestampHandlerInterface to
define your own session id validating method like validate_sid and the timestamp updating method like update_timestamp in the non-OOP prototype of session_set_save_handler().
SessionUpdateTimestampHandlerInterface is a new interface introduced in PHP 7.0, which has not been documented yet. It has two abstract methods: SessionUpdateTimestampHandlerInterface :: validateId($sessionId) and SessionUpdateTimestampHandlerInterface :: updateTimestamp($sessionId, $sessionData).
<?php
/*
@author Wu Xiancheng
Code structure for PHP 7.0+ only because SessionUpdateTimestampHandlerInterface is introduced in PHP 7.0
With this class you can validate php session id and update the timestamp of php session data
with the OOP prototype of session_set_save_handler() in PHP 7.0+
*/
class PHPSessionXHandler implements SessionHandlerInterface, SessionUpdateTimestampHandlerInterface {
public function close(){
// return value should be true for success or false for failure
// ...
}
public function destroy($sessionId){
// return value should be true for success or false for failure
// ...
}
public function gc($maximumLifetime){
// return value should be true for success or false for failure
// ...
}
public function open($sessionSavePath, $sessionName){
// return value should be true for success or false for failure
// ...
}
public function read($sessionId){
// return value should be the session data or an empty string
// ...
}
public function write($sessionId, $sessionData){
// return value should be true for success or false for failure
// ...
}
public function create_sid(){
// available since PHP 5.5.1
// invoked internally when a new session id is needed
// no parameter is needed and return value should be the new session id created
// ...
}
public function validateId($sessionId){
// implements SessionUpdateTimestampHandlerInterface::validateId()
// available since PHP 7.0
// return value should be true if the session id is valid otherwise false
// if false is returned a new session id will be generated by php internally
// ...
}
public function updateTimestamp($sessionId, $sessionData){
// implements SessionUpdateTimestampHandlerInterface::validateId()
// available since PHP 7.0
// return value should be true for success or false for failure
// ...
}
}
?>
The non-OOP prototype of session_set_save_handler() supports validate_sid and update_timestamp as of PHP 7.0 while the OOP prototype doesn't even in PHP 7.2. However the OOP prototype does support create_sid since PHP 5.5.1.
validate_sid($sessionId)
This callback is to validate $sessionId. Its return value should be true for valid session id $sessionId or false for invalid session id $sessionId. If false is returned, a new session id is generated to replace the invalid session id $sessionId.
update_timestamp($sessionId)
This call back is to update timestamp, and its return value should be true for success or false for failure.
As of PHP 5.5.1, another method create_sid() is supported. It will be called when session_regenerate_id() is invoked.
SessionHandlerInterface {
/* Methods */
abstract public bool close ( void )
abstract public bool create_sid ( void )
abstract public bool destroy ( string $session_id )
abstract public bool gc ( int $maxlifetime )
abstract public bool open ( string $save_path , string $session_name )
abstract public string read ( string $session_id )
abstract public bool write ( string $session_id , string $session_data )
}
Note that session_start( ) calls open then read and the class returns true for open and the value of session or empty for read.
Well, then there is no catch for errors, this is, session_start() must return false on failure, but that is not the case for the class implementation on method open, no matter if you return true or false or whatever from open, it is ignored by session_start() function and proceeds to read method
A bug?, if open returns false, session_start() should stop the next step (read) and return itself false
if(session_start()) ...code
else exit( );
So forget about session_start() return value, you need to implement an error catch routine and exit() in case of failure on open method
You should prepend <b>\</b> before class name, to tell php its from root namespace.
Your custom session handler should not contain calls to any of the session functions, such as session_name() or session_id(), as the relevant values are passed as arguments on various handler methods. Attempting to obtain values from alternative sources may not work as expected.
If you want to use type declarations in your own session handling class, don't "implements" the SessionHandlerInterface, SessionIdInterface, or SessinUpdateTimestampInterface, otherwise you will get a fatal error saying that declaration of the class method must be compatible with the interface method.
a bad example
<?php
class SessionWuXianchengHandler implements SessionHandlerInterface {
public function open(string $sessionPath, string $sessionName) : bool {
}
......
}
?>
a good example
<?php
class SessionWuXianchengHandler {
public function open(string $sessionPath, string $sessionName) : bool {
}
......
}
?>