PHP存储Session

一 Redis

方法一:  配置文件php.ini,修改为下面内容,保存并重启服务

session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"

方法二:  直接在代码中加入以下内容:

<?php  
ini_set("session.save_handler", "redis");
ini_set("session.save_path", "tcp://127.0.0.1:6379");
?>

如果redis配置文件redis.conf里设置了连接密码requirepass,save_path需要这样写tcp://127.0.0.1:6379?auth=连接密码

二 Memcache

方式一:  php.ini 文件,修改下面两个参数:

session.save_handler = memcache  
session.save_path = "tcp://Mem服务器1:端口号,tcp://Mem服务器2:端口号..."

方式二: 在 php 文件中使用 ini_set 函数

<?php  
ini_set("session.save_handler", "memcache");  
ini_set("session.save_path", "tcp://Mem服务器1:端口号,tcp://Mem服务器2:端口号...");  
?>

如果安装的PECL是memcached(使用libmemcache库的那个),则配置应为:

ini_set("session.save_handler", "memcached"); // 不是memcache
ini_set("session.save_path", "127.0.0.1:11211"); // 不要tcp:

 

三 回调函数方式

bool session_set_save_handler ( callable $open , callable $close , callable $read , callable $write , callable $destroy , callable $gc , callable $create_sid )

  • open
    自动开始会话或者通过调用 session_start() 手动开始会话之后第一个被调用的回调函数。 成功返回 TRUE,反之返回 FALSE

  • close
    回调函数类似于类的析构函数。脚本执行完成调用 session_write_close() session_destroy() 时被执行,即在所有session操作完后被执行。

  • read
    会话读取数据,read 回调函数必须返回将会话 数据编码(序列化)后的字符串。 如果会话中没有数据,read 回调函数返回空字符串。 在调用 read 之前,PHP 会调用 open 回调函数。read 回调返回的序列化之后的字符串格式必须与 write 回调函数保存数据时的格式完全一致。 PHP 会自动反序列化返回的字符串并填充 $_SESSION 超级全局变量。 虽然数据看起来和 serialize() 函数很相似, 但是需要提醒的是,它们是不同的。 请参考: session.serialize_handler

  • write
    会话保存数据。 此回调函数接收当前会话 ID 以及 $_SESSION 中数据序列化之后的字符串作为参数。 序列化会话数据的过程由 PHP 根据 session.serialize_handler 设定值来完成。PHP 会在脚本执行完毕或调用 session_write_close() 函数之后调用此回调函数。 注意,在调用完此回调函数之后,PHP 内部会调用 close 回调函数。
    PHP 会在输出流写入完毕并且关闭之后 才调用 write 回调函数, 所以在 write 回调函数中的调试信息不会输出到浏览器中。 如果需要在 write 回调函数中使用调试输出, 建议将调试输出写入到文件。

  • destroy
    当调用 session_destroy()函数, 或者调用session_regenerate_id()函数并且设置 destroy 参数为 TRUE 时, 会调用此回调函数。

  • gc
    清理会话中的旧数据,PHP 会不时的调用垃圾收集回调函数。 调用周期由 session.gc_probability session.gc_divisor参数控制。 传入到此回调函数的 lifetime 参数由 session.gc_maxlifetime 设置。

  • create_sid
    当需要新的会话 ID 时被调用的回调函数。

<?php 


class FileSessionHandler { 
    
    private $savePath;  
    //启动session
    function open($savePath, $sessionName) { 
        $this->savePath = $savePath; 
        if (!is_dir($this->savePath)) { 
            mkdir($this->savePath, 0777); 
        } 
        return true;
    } 
    
    //关闭session 
    function close() { 
        return true;
    } 
    
    //读取session 
    function read($id) { 
        return (string)@file_get_contents("$this->savePath/sess_$id"); 
    } 
    
    //写入session 
    function write($id, $data) { 
        return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true; 
    } 

    //销毁session 
    function destroy($id) { 
        $file = "$this->savePath/sess_$id"; 
        if (file_exists($file)) { 
            unlink($file); 
        } 
        return true; 
    } 

    //销毁session 
    function gc($maxlifetime) { 
        foreach (glob("$this->savePath/sess_*") as $file) { 
            if (filemtime($file) + $maxlifetime < time() && file_exists($file)) { 
                unlink($file); 
            } 
        } 
        return true; 
    } 

} 

$handler = new FileSessionHandler(); 

session_set_save_handler( 
    array($handler, 'open'), 
    array($handler, 'close'), 
    array($handler, 'read'), 
    array($handler, 'write'), 
    array($handler, 'destroy'), 
    array($handler, 'gc')
); 
// 下面这行代码可以防止使用对象作为会话保存管理器时可能引发的非预期行为
// 脚本执行完毕之后,内部会清除对象,有可能不调用 write 和 close 回调函数。
register_shutdown_function('session_write_close'); 
session_start(); 
// 现在可以使用 $_SESSION 保存以及获取数据了

四 会话类处理类

使用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); 
    } 
} 

ini_set('session.save_handler', 'files'); 
$key = 'secret_string'; 
$handler = new EncryptedSessionHandler($key); 
session_set_save_handler($handler, true); 
session_start();

五 会话管理器接口

PHP > 5.4

//Database 
CREATE TABLE `Session` ( 
    `Session_Id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,             
    `Session_Expires` datetime NOT NULL, 
    `Session_Data` text COLLATE utf8_unicode_ci, 
    PRIMARY KEY (`Session_Id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 
SELECT * FROM mydatabase.Session;
<?php 

class SysSession implements SessionHandlerInterface { 
    private $link; 
    //开启session 
    public function open($savePath, $sessionName) { 
        $link = mysqli_connect("server","user","pwd","mydatabase"); 
        if($link){ 
            $this->link = $link; 
            return true; 
        }else{ 
            return false; 
        } 
    } 

    //关闭session 
    public function close() { 
        mysqli_close($this->link); 
        return true; 
    } 

    //读取session 
    public function read($id) { 
        $sql = "SELECT Session_Data FROM Session WHERE Session_Id = '".$id."' AND Session_Expires > '".date('Y-m-d H:i:s')."'"; 
        $result = mysqli_query($this->link,$sql); 
        if($row = mysqli_fetch_assoc($result)){ 
            return $row['Session_Data']; 
        }else{ 
            return ""; 
        } 
    } 

    //写入session 
    public function write($id, $data) { 
        $DateTime = date('Y-m-d H:i:s'); 
        $NewDateTime = date('Y-m-d H:i:s',strtotime($DateTime.' + 1 hour')); 
        $sql = "REPLACE INTO Session SET Session_Id = '".$id."', Session_Expires = '".$NewDateTime."', Session_Data = '".$data."'"; 
        $result = mysqli_query($this->link,$sql ); 
        if($result){ 
            return true; 
        }else{ 
            return false; 
        } 
    } 

    //销毁session 
    public function destroy($id) { 
        $sql = "DELETE FROM Session WHERE Session_Id ='".$id."'"; 
        $result = mysqli_query($this->link,$sql); 
        if($result){ 
            return true; 
        }else{ 
            return false; 
        } 
    } 

    //回收session 
    public function gc($maxlifetime) { 
        $sql = "DELETE FROM Session WHERE ((UNIX_TIMESTAMP(Session_Expires) + ".$maxlifetime.") < ".$maxlifetime.")"; 
        $result = mysqli_query($this->link,$sql); 
        if($result){ 
            return true; 
        }else{ 
            return false; 
        } 
    } 

} 


$handler = new SysSession(); 
// 下面这行代码可以防止使用对象作为会话保存管理器时可能引发的非预期行为 
session_set_save_handler($handler, true);
原文地址:https://www.cnblogs.com/lpblogs/p/7462507.html