深入理解 Session 和 Cookie

xiaoxiao2021-02-28  25

Q:如何精确的让Session 的有效期为30分钟呢?

初衷都是为了记住用户在网站上的浏览信息,由于http 是无状态的,为了维持用户在网站的状态

1 来看看 php 是如何设置 session 的有效期的

#超过这个秒数,储存的数据会被当作垃圾,并且被垃圾回收进程清除 #http://php.net/session.gc-maxlifetime session.gc_maxlifetime = 1440

ok,默认是24分钟

2 看看 session.gc 的启动概率和方案1:修改session.gc来限制session的lifetime

假设,我的一个session 刚刚到期了,那么这个session 是否会被立刻当作 garbage 被gc回收呢?答案是不一定的,那么gc 工作的启动概率是怎么算的呢?

; # 以下为自翻 (英文原文档 http://php.net/session.gc-probability) ; # 定义gc 进程启动的概率 ; # 在每一个session 初始化的时候,启动率都会被计算一次 ; # gc_probability/gc_divisor. 在该方程式中 session.gc_probability 是分子,gc_divisor 是分母. 设置分子值为1,当分母也就是gc_divisor为100,会有 1% 的概率,GC将在任何给定请求下运行。 ; #gc_probability ; #默认值: 1 ; #开发环境默认值: 1 ; #生产环境默认值: 1 session.gc_probability = 1 ; # gc_divisor 配成1000 分子配成 1 ; Default Value: 100 ; Development Value: 1000 ; Production Value: 1000 ; http://php.net/session.gc-divisor session.gc_divisor = 1000

可以看出来在 php.ini 中给出的设置 默认 gc 在 session init 的时候的自启动概率为 1% 。实际上,如果你提高了方程式的结果值,这样提高自启动概率,这样虽然可以,但是也不是一个非常好的办法。

第一 .这样做会降低性能。第二 . php 通过 stat命令扩展: stat $ stat php.ini # res 文件:"php.ini" 大小:70716 块:144 IO 块:4096 普通文件 设备:fd01h/64769d Inode:1338283 硬链接:1 权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root) 最近访问:2018-03-06 11:15:20.518507981 +0800 最近更改:2017-12-11 16:50:26.673092377 +0800 最近改动:2017-12-11 16:50:26.677092378 +0800 创建时间:-

这个命令 来获取和判断 文件的更新时间,而默认 单独 session 存储是一个文件,假设你设置了一个 sessionA 包含kv a=1 ,你希望30分钟更新,然而在这期间,你又更新了sessionA 添加了b=2 ,那么a=1 将无法在预期时间得到正确回收。

所以,修改gc启动概率来限制session的 expiretime 并不是一个很好的方法

# 设置 cookie 中的 session 的存活时间 . session.cookie_lifetime = 0

这个过期只是Cookie过期, 换个说法这点就考察Cookie和Session的区别, Session过期是服务器过期, 而Cookie过期是客户端(浏览器)来保证的, 即使你设置了Cookie过期, 这个只能保证标准浏览器到期的时候, 不会发送这个Cookie(包含着Session ID), 而如果通过构造请求, 还是可以使用这个Session ID的值.————引用自 鸟哥的博客 。

也就是说你无法通过gc 来回收这个Session,虽然访问时候不传递给服务器了,但是 session 还是存在服务器中。

4 使用 redis 等 来控制 Session 过期时间

使用 redis 来保存 session ,并且设置 timeout ,redis 的回收机制不是按照几率来的,可以保证到期就回收。

扩展:redis 的 回收机制 惰性删除:当你去操作一个键(譬如 get name),redis首先会检查这个键是否关联了一个超时时间,如果有,则检查是否超时,若超时则返回空,否则返回相应的值;所以即使redis 的gc 没有回收也不会返回,redis底层已经帮助你做了过期判断。定时删除:redis中有个时间事件,它会清理数据库中已经过期的键(redis会限定该操作占用的时间,避免阻塞客户端的请求)

5 使用 php 来控制 Session 过期时间

设置Cookie过期时间30分钟, 并设置Session的lifetime也为30分钟. <?php class Session { public static function set($name, $data, $expire = 1800) { $session_data = array(); $session_data['data'] = $data; # 为每一个Session值增加 当前时间基础上的 过期时间 expire. $session_data['expire'] = time() + $expire; $_SESSION[$name] = $session_data; } public static function get($name) { if (isset($_SESSION[$name])) { if ($_SESSION[$name]['expire'] > time()) { return $_SESSION[$name]['data']; } else { self::clear($name); } } return false; } private static function clear($name) { unset($_SESSION[$name]); } } <?php session_start(); $data = '123456'; session::set('test', $data, 10); # 访问之前, 判断时间戳. echo session::get('test'); # 未过期,输出 sleep(10); echo session::get('test'); # 已过期 扩展: Cookie 和 Session 的区别

画了张简易流程图 cookie 和 session 一起的工作原理:

保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID。但cookie可以被人为的禁止 ,经常被使用的一种技术叫做URL重写,表单隐藏字段,这两种方式都是以kv 把 session_id 传给服务器。

Cookie 和 Session 的区别:

Cookie中只能保管ASCII字符串,而Session中能够存取任何类型的数据。

Cookie存储在客户端阅读器中,对客户端是可见的 而Session存储在服务器上,对客户端是透明的,不存在敏感信息泄露的风险。

Cookie支持跨域名访问,例如将domain属性设置为“.leon0204.com”,则以“.leon0204.com”为后缀的一切域名均能够访问该Cookie。 而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。

假如客户端支持Cookie,则Cookie既能够设为本浏览器窗口以及子窗口内有效(把过期时间设为–1),也能够设为一切阅读器窗口内有效(把过期时间设为某个大于0的整数)。但Session只能在本阅读器窗口以及其子窗口内有效。假如两个浏览器窗口互不相干,它们将运用两个不同的Session。

Session是保管在服务器端的,每个用户都会产生一个Session。假如并发访问的用户十分多,会产生十分多的Session,耗费大量的内存。因而像Google、Baidu、Sina这样并发访问量极高的网站,是不太可能运用Session来追踪客户会话的。而Cookie保管在客户端,不占用服务器资源。假如并发阅读的用户十分多,Cookie是很好的选择。

转载请注明原文地址: https://www.6miu.com/read-1700133.html

最新回复(0)