PHPSESSION机制原理详解
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”
2. session.save_path :string
session.save_path确认了传递给存储处理器的参数。如果选择了默认的 files ⽂件处理器,则此值是创建⽂件的路径。默认为/tmp,此指令还有⼀个可选的 N 参数来决定会话⽂件分布的⽬录深度,如session.save_path=‘2;/tmp’。N不宜太⼤,不然I/O 太多,很影响性能。
3. session.name :string
session.name定义了sessionID名以⽤做 cookie 的名字。只能由字母数字组成,默认为 PHPSESSID。
4. session.auto_start :bool
session.auto_start 定义了session扩展是否⾃动开启,默认0,所以我们在使⽤session时要session_start()。
5. session.use_cookies : bool
定义session是否指定客户端⽤cookie存储PHPSESSID
6. session.use_only_cookies : bool
定义session是否指定客户端只能⽤cookie存储PHPSESSID
7. session.use_trans_sid : bool
定义session是否启⽤透明 SID ⽀持,这样可以将PHPSESSID作为URl的参数来管理,默认为 0(禁
⽤)
8. _probability : int
<_probability 与 _divisor 合起来⽤来管理 gc(garbage collection 垃圾回收)进程启动的概率。默认为 1。
9. _divisor :int
<_divisor 与 _probability 合起来定义了在每个会话初始化时启动 gc(garbage collection 垃圾回收)进程的概率。此概率⽤ gc_probability/gc_divisor 计算得来。例如 1/100 意味着在每个请求中有 1% 的概率启动 gc 进程。
<_divisor 默认为 100。
10. _maxlifetime :int
<_maxlifetime 指定过了多少秒之后数据就会被视为“垃圾”并被清除。你可以将gc_divisor设为1,gc_maxlifetime设为10,来看gc回收的现象,如果save_handler值为files,就是将过期的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,"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;
}
/**
php8兼容php7吗
* 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//在读取完会话数据之后,⽴即关闭会话存储⽂件,不做任何修改
]);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论