PHP SESSION机制原理详解

SESSION基础

session 即会话,它与cookie类似,是记录用户行为状态的机制,只不过cookie将用户状态信息放在客户端(浏览器),session是把信息以一定的数据结构(通常由sessionID和内容组成)放在服务端,存储容器可以是文件(最常用)、RDB(mysql,postgresql,sqlLite等)、NoSql(redis,memcache)等,它的正常工作依赖于http协议助其完成客户端与服务端的交流,最常见的是借用http header头的cookie,PHP默认就是用cookie,还可以借用url参数,html的隐藏表单域等,但后两者不够方便,并且实践证明用户很少会禁用cookie。其实单台服务器用文件存储seesion内容就可以了,多台的话一定要用数据库的,防止找不到相应的seesion。
工作原理如下图:

在这里插入图片描述PHP中一般借用session扩展(php内置)进行session的管理:

session_id($sessionID);//设置或获取sessionID,放在session_start()之前
session_start();//开启session扩展
$_SESSION['token'] = 'shjsals1212klasssu80';//利用超全局变量$_SESSION设置session内容
echo $_SESSION['token'];//获取当前sessionID下的某一个session值

SESSION(运行时)配置

session运行时配置即在php.ini文件中进行session的配置。常用的如下:

  1. session.save_handler :string

session.save_handler 确定了存储session用的处理器的名字,默认files,如果想改成memcache,可以这样写:
session.save_handler = memcache,session.save_path = “tcp://127.0.0.1:8888”

  1. session.save_path :string

session.save_path确认了传递给存储处理器的参数。如果选择了默认的 files 文件处理器,则此值是创建文件的路径。默认为 /tmp,此指令还有一个可选的 N 参数来决定会话文件分布的目录深度,如session.save_path=‘2;/tmp’。N不宜太大,不然I/O太多,很影响性能。

  1. session.name :string

session.name定义了sessionID名以用做 cookie 的名字。只能由字母数字组成,默认为 PHPSESSID。

  1. session.auto_start :bool

session.auto_start 定义了session扩展是否自动开启,默认0,所以我们在使用session时要session_start()。

  1. session.use_cookies : bool

定义session是否指定客户端用cookie存储PHPSESSID

  1. session.use_only_cookies : bool

定义session是否指定客户端只能用cookie存储PHPSESSID

  1. session.use_trans_sid : bool

定义session是否启用透明 SID 支持,这样可以将PHPSESSID作为URl的参数来管理,默认为 0(禁用)

  1. session.gc_probability : int

session.gc_probability 与 session.gc_divisor 合起来用来管理 gc(garbage collection 垃圾回收)进程启动的概率。默认为 1。

  1. session.gc_divisor :int

session.gc_divisor 与 session.gc_probability 合起来定义了在每个会话初始化时启动 gc(garbage collection 垃圾回收)进程的概率。此概率用 gc_probability/gc_divisor 计算得来。例如 1/100 意味着在每个请求中有 1% 的概率启动 gc 进程。session.gc_divisor 默认为 100。

  1. session.gc_maxlifetime :int

session.gc_maxlifetime 指定过了多少秒之后数据就会被视为“垃圾”并被清除。你可以将gc_divisor设为1,gc_maxlifetime设为10,来看gc回收的现象,如果save_handler值为files,就是将过期的session文件删除。

这些是常用的,详情见官网session运行中配置

SESSION函数

函数也列出一些常用的,详情见官网session函数

  • session_id($sessionID);//设置或获取sessionID,放在session_start()之前
  • session_start();//开启session扩展
  • $_SESSION[‘token’] = ‘shjsals1212klasssu80’;//利用超全局变量$_SESSION设置
  • $_SESSION[‘token’];//获取当前sessionID下的某一个session值
  • unset($_SESSION[‘token’]);//释放指定的session变量,注意请不要使用unset($_SESSION)来释放整个$_SESSION, 因为它将会禁用通过全局$_SESSION去注册会话变量
  • session_unset();//释放所有的session变量,等价于$_SESSION=[];
  • session_destroy//销毁当前sessionID对应的数据(如果save_hander=files,则删除相应的文件), 但是不会重置当前会话所关联的全局变量, 就是不改变内存中$_SESSION值。 如果需要再次使用会话变量, 必须重新调用 session_start() 函数。可以通过isset($_SESSION[‘token’])来认识其差别

SESSION类和接口

php为用户提供了一个接口,SessionHandlerInterface,用户可以自定义seesion管理。

官方提示:SessionHandlerInterface是一个接口,它定义了用于创建自定义会话处理程序的原型。自定义seesion处理类必须实现此接口,若需要调用自定义类,必须将该类的实例传递给session_set_save_handler()。
请注意,该类的回调方法设计为由PHP内部调用,而不是从用户空间代码调用。
SessionHandlerInterface定义了几个方法:

SessionHandlerInterface {
/* 方法 */
abstract public close ( void ) : bool
abstract public destroy ( string $session_id ) : bool
abstract public gc ( int $maxlifetime ) : int
abstract public open ( string $save_path , string $session_name ) : bool
abstract public read ( string $session_id ) : string
abstract public write ( string $session_id , string $session_data ) : bool
}

接口的抽象方法作用如下:
在这里插入图片描述简单代码实例(redis):

class SessionManager{
  private $redis;
  private $sessionSavePath;
  private $sessionName;
  private $sessionExpireTime = 30;
  public function __construct(){
    $this->redis = new Redis();
    $this->redis->connect('127.0.0.1',6379);  //连接redis
    //注册类
    ini_set('session.save_handler','user');
    $retval = session_set_save_handler(
      array($this,"open"),
      array($this,"close"),
      array($this,"read"),
      array($this,"write"),
      array($this,"destory"),
      array($this,"gc")
    );
      session_start();
  }
    
    public function open($path,$name){
      return true;
    }
    public function close(){
      return true;
    }
    /** 
     * read session by session_id 
     * @param string $session_id 
     * @return mixed 
     */  
    public function read($id){
      $value = $this->redis->get($id);
      if($value){
        return $value;
      }else{
        return "";
      }
    }
    public function write($id,$data){
      if($this->redis->set($id,$data)){
        $this->redis->expire($id,$this->sessionExpireTime); 
         //设置过期时间
        return true;
      }
      return false;
    }
    public function destory($id){
      if($this->redis->delete($id)){
        return true;
      }
      return false;
    }
    /** 
     * this function is no use because of redis expire 
     * @param int $maxlifetime 
     * @return bool 
     */  
    public function gc($maxlifetime){
      return true;
    }
    //析构函数
    public function __destruct(){
      session_write_close();
    }
      
}
$session = new SessionManager();
$_SESSION['fpf'] = "pop";
echo $_SESSION['fpf'];
就目前我所用到的php框架,CI和Laravel都基于这个接口对重新设计了seesion管理,可以下载源码进行学习,非常棒的学习资料。

提示:

php也允许开发者以很简单的方式将session存储器由默认的files替换为redis或memcache,只需要下载相应的扩展即可。以redis为例:
ini_set(“session.save_handler”, “redis”);
ini_set(“session.save_path”, “tcp://127.0.0.1:6379”);
session_start();
$_SESSION[“user”]=“sgao”;
如果可以修改php.ini文明加密,可以直接改session.save_handler和session.save_path值。

特别注意的是一定要有redis扩展,通过phpinfo()查看如下图:
在这里插入图片描述如果没有redis扩展,红色圈定部分只有files和user这两个选项的,当然,你下了memcache扩展,这里就会出现memcache选项。

PHP7 SESSION新特性

php7之前session_start()函数是不可传参的,但php7可以了,例如:

<?php
session_start([
   'cache_limiter' => 'private', //在读取完毕会话数据之后马上关闭会话存储文件
    'cookie_lifetime'=>3600, //SessionID在客户端Cookie储存的时间,默认是0,代表浏览器一关闭SessionID就作废
    'read_and_close'=>true //在读取完会话数据之后, 立即关闭会话存储文件,不做任何修改
]);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值