会话控制

当输出session_start()的时候session会话控制就开始了,我们浏览网站,服务器是识别不了用户的身份的,所以就有了session来控制。使用session会发给客户端浏览器的一个令牌也就是cookie。当用户在应用程序的 Web 页之间跳转时,因为 cookie 存在浏览器中、每次都带上令牌,而在令牌没有过期之前整个用户会话中一直存在下去。

为什么要把session存入数据库,或者共享?

像那些大网站例如百度、腾讯、当你访问新闻和首页,他的二级域名是不一样的,但是也不可能每个域下都让用户去登录。一影响用户的体验,二我个人觉得非常麻烦。所以就有session的一个共享,就是登录一次,其他页面免登陆。也可以说是单点登录吧。

写入数据库应该算是对session的一个扩展,如果说着个是大流量的网站那么,那么session的回收处理,可能对系统性能造成一定的影响,影响性能的原因之一文件系统,在同一个目录下超过10000个文件时,文件的定位将非常耗时。

如果你是多台服务,PHP默认存储session会话是文件形式,其他服务器是访问不到的。

那把session写入数据库有啥好处呢?

控制一个帐号只能一个人登录 统计在线人数 踢出某个在线用户 多站点共享等等。

那说一下php操作session的一个重要函数session_set_save_handler()。调用他需要6个参数次序分别为

  1. 启动会话
  2. 关闭会话
  3. 读取会话数据
  4. 写入会话数据
  5. 销毁会话数据
  6. 垃圾回收程序

列子,按照执行顺序排列

$sdbc = NULL;
// ini_set('session.serialize_handler','php_serialize');
//自己指定的用户session_id
session_id("nmfd7cnp6j9iib8lv0fg6bu514");

function open_session() {
    global $sdbc;
    
  
    $sdbc = mysqli_connect ('localhost', 'root', '123456', 'test');
    var_dump(1);
    return true;
} 
 


function read_session($sid) {
    global $sdbc;
    var_dump($sid);
      var_dump(2);
    

    $q = sprintf('SELECT data FROM sessions WHERE id="%s"', mysqli_real_escape_string($sdbc, $sid)); 
    $r = mysqli_query($sdbc, $q);
    

    if (mysqli_num_rows($r) == 1) {
        list($data) = mysqli_fetch_array($r, MYSQLI_NUM);
 
     
        return $data;

    } else {
        return '';
    }
} 
function write_session($sid, $data) {
    global $sdbc;
    var_dump(3);
    var_dump($data);
    $q = sprintf('REPLACE INTO sessions (id, data) VALUES ("%s", "%s")', mysqli_real_escape_string($sdbc, $sid), mysqli_real_escape_string($sdbc, $data)); 
    var_dump($q);
    $r = mysqli_query($sdbc, $q);
    var_dump($r);

    return true;
} 
//此步骤只有在销毁session的时候执行
function destroy_session($sid) {
    global $sdbc;
    var_dump(4);
    
    $q = sprintf('DELETE FROM sessions WHERE id="%s"', mysqli_real_escape_string($sdbc, $sid)); 
    $r = mysqli_query($sdbc, $q);
    
    
    $_SESSION = array();

    return true;
}

function clean_session($expire) {
    global $sdbc;
    
var_dump(5);
var_dump($expire);
    
    $q = sprintf('DELETE FROM sessions WHERE DATE_ADD(last_accessed, INTERVAL %d SECOND) < NOW()', (int) $expire); 
    $r = mysqli_query($sdbc, $q);
    file_put_contents('33.txt',$expire);
    return true;
} 

function close_session() {
    global $sdbc;
      var_dump(6);
    return mysqli_close($sdbc);
} 

session_set_save_handler('open_session', 'close_session', 'read_session', 'write_session', 'destroy_session', 'clean_session');


session_start();

$_SESSION['id']=1;
$_SESSION['name']='启东';
var_dump($_SESSION);

然后修改了一下php.ini的配置文件

session.gc_divisor = 1 //初始值为1000
session.gc_maxlifetime = 10 //初始值为1440 为了看执行效果特意修改

下面来看一张图片

图片1

这张图片为代码执行后的结果 数字5代表垃圾回收10代表时间。

图片2

知道了这些步骤我们可以做很多事情,就像统计用户在线人数等。

在初学PHP的时,曾经说聊天室功能(那时还不知道websocket),现在利用session会话就能实现。

如何实现共享?

用户访问服务器端的时候,会响应发送个cookie,而浏览器会存储个cookie,用来识别你是否访问过这个网站,里面还会存储点信息。这里还涉及到一个cookie域的问题。

这个实现其实很简单,只需要对 COOKIE 的域(domain)进行特殊地设置即可,默认情况下,COOKIE 的域是当前服务器的域名/IP 地址,而域不同的话,各个服务器所设置的 COOKIE 是不能相互访问的。下面是设置的配置项

ini_set('session.use_cookies',1);
ini_set('session.cookie_path','/');
ini_set('session.cookie_domain','');//因为的是本地环境,就没有填写,顶级域

那么说一下存入数据库的session序列化。我知道一共有三种

1.默认的为php 序列化的样式为 键名+竖线+经过serialize()函数反序列处理的值
name|s:2:"tb"; //我并没有找到直接反序列化的函数

2.php_serialize (php>=5.5.4) 经过serialize()函数反序列处理的数组
a:2:{s:2:"id";i:1;s:4:"name";s:7:"启动1";} //反序列化函数unserialize();方便 ...推荐使用

3.php_binary 键名的长度对应的ASCII字符+键名+经过serialize() 函数反序列处理的值
idi:1;names:7:"启动1";写入数据库是这样。目前没找到更好更方便的反序方案

Last modification:January 4, 2020
如果觉得我的文章对你有用,请随意赞赏