对比cookie
cookie的缺点:
- 会话数据原文存储于浏览器端,原始数据的安全性较低。
- 如果cookie数据量较大,由于每次请求都要携带,会增加带宽的使用。
如何解决这两个问题呢?
使用session技术来实现。将会话数据存储于服务器端。同时使会话数据可以区分浏览器。
为每个会话数据建立独立的会话数据区(来存储当前会话的全部数据),每个会话数据区都存在唯一的标志,同时浏览器端存储该唯一标志(携带的少!),做配对使用!
相对cookie安全一些,但是也可以伪造(直接使用别人的session id)。
开启session机制
函数:session_start();
也可以通过php.ini设置为自动开启,设置session.auto_start();
利用$_SESSION操作session数据
增,删,改,查,都是使用$_SESSION完成,每个元素就是一个session数据,元素的键就是session数据的名,元素的值就是数据。
每一个脚本周期之内想读session必须先开启!
session原理
存储于浏览器端cookie中的session-id,就是一个普通的cookie变量,不过具有特殊的意义。
每个会话,所生成存储于服务器端的session数据区。默认的,以文件的形式,存储于服务器端操作系统的临时目录中。
session数据属性
- 有效期:会话周期
- 有效路径:默认有效路径整站有效。和cookie不一样,不仅子目录可以保持session,回到父目录session同样存在。
- 有效域:默认仅在当前域有效
- 是否仅安全连接传输:否
- 是否httponly:
以上session数据的特征,都是由,浏览器cookie中所存储的session-id cookie变量所导致的。
可见,如果需要更改session数据的属性,则需要更改存储session-id的cookie变量PHPSESSIONID的属性。
- php.ini中存在该属性的配置。此种方法会影响其他脚本。
- 通过在脚本中, 使用函数int_set()来进行配置的修改,仅在设置后的脚本周期内有效,要保证在开启session前设置完毕。ini_set(‘选项’, ‘值’);
- 使用特定的功能函数,session_set_cookie_params(有效期,有效路径,有效域,是否仅安全传输,是否httponly)完成设置。注意必须在session_start()之前设定,有效期是一个时间间隔。
选项的设置是针对cookie中的session-id的,所有的session数据有效。
session的数据通常保持默认值,不建议修改!如果某个数据需要长时间保存,建议用cookie,因为cookie保存在浏览器端,不会对服务器造成压力。
语法
cookie数据必须是字符串类型,session可以使任何类型。因为session的数据时序列化存储的。不过不包含资源类型!
session_start()之前不能有输出!
session数据区
在脚本周期结束后,持久存储当前会话session数据的区域。
在脚本周期内,使用$_SESSION这个变量管理的会话session数据。
销毁
session_destroy()函数。
销毁:删除当前的数据区,关闭session机制。在销毁session后,由于$_SESSION变量在内存中,所以还可以用,只是不会结束时不会写入到数据区了。因此,下次脚本周期不能获取存储的session数据了。
面试题1:如何完整删除与当前session相关的全部数据?
(分析:删除数据区,删除$_SESSION变量)。
- session_destroy(); 删除数据区
- unset($_SESSION); 销毁变量
- setCookie(session_name(), ”, time()-1),销毁cookie中的session-id
tip:PHPSESSID,称之为session.name可以被配置的php.ini,使用函数session_name()来获取当前的值。
面试题2:如何清空session数据?
不要unset(SESSION),需要_SESSION = array();
重写session的存储机制:
目的:
- 便于管理大量的session数据
- 便于web服务器集群钟祥session数据
方案:入库,入内存
实现过程:
定义(实现)自定义的相关存储处理函数。将其设置为session机制需要的存储函数(告知session机制,使用我们的函数完成存储处理)
session机制,共需要6个存储处理函数。使用php函数,session_set_save_handler(开始处理器,结束处理器,读处理器,写处理器,删除处理器,垃圾回收处理器)。
使用数据库存储
读操作
直接从数据区读即可。
写操作
写操作不需要每次都执行,如果已经插入过了,只需要替换即可。
insert into ... ON DUPLICATE KEY UPDATE
REPLACE 语法与isnert一致,存在则替换,不存在则插入
删除操作
在开启session机制的过程中,有概率的执行垃圾回收操作。默认的概率为1/1000。可以配置:
session.gc_probability = 1
session.gc_divisor = 1000
垃圾回收操作
PHP session机制设置session数据区的最大有效期,某条session记录(数据区),在最后一次处理后,如果超过了多久之后没有被使用,则被视为垃圾数据。
该时间默认1440s,可以被配置(php.ini中)。
同时需要记录每个session数据区的最后处理时间。与当前时间比较,如果之差大于1440,则说明已经过期。
所以,我们在数据库中需要增加字段,来存储最后处理时间。
垃圾回收是被基本上是别的浏览器触发的!因为先读后垃圾回收再写,回收了一次但又写了一次,相当于没有垃圾回收,并且还把时间戳更新了。
开始
session开启时,最早执行的一个存储机制的相关方法,用于初始化存储操作的相关资源。比如,连接数据库。
结束
在session机制关闭时,执行的方法,最后一个执行的存储相关操作,用于收尾性工作。
补充
先执行session_set_save_handler(),再执行session_start()。
保证session不自动开启,在php.ini中让session_auto_start=0。Appache可以通过.htaccess文件配置,php_flag session.auto_start 0(我没用Apache:))。
配置php.ini中session.save_handler默认为files。建议:重写session存储机制后, 应该将其改为user表示用户自定义!
代码中调用玩session_set_save_handler()函数之后调用:
ini_set('session.save_handler', 'user');
cookie和session的差异
联系:
- 都是实现会话的方案。
- session基于cookie。
差异:
cookie | session |
---|---|
会话存储位置 | 浏览器端 |
安全性 | 低 |
数据传输量 | 大 |
支持会话数据量 | 参考限制:4k,20个 |
支持的数据类型 | 字符串 |
session数据的持久化问题
修改两点:
浏览器端的session-id:session_set_cookie_params(时间);
服务器端session数据区:ini_set(‘session.gc_maxlifetime’, ‘时间’);
session很少做持久化,所以如果需要持久存储就去选择cookie。
cookie仅用,session是否可用?
常规;cookie禁用,session不能使用。
技术上,可以使用:cookie用来存储session的id,每次请求时携带。通过GET或POST的方式向服务器传递session-id。
PHP提供的配置:
session.use_only_cookies = 1
session.use_trans_sid = 0
同样可以用ini_set函数修改。