1. 文档阅读
https://blog.csdn.net/matthis_meng/article/details/80530927 // 一个浏览器最多可以产生多少个cookie,每个cookie 文件最大不能超过多少?
https://www.jianshu.com/p/9fb978b1d811 // 各浏览器Cookie大小、个数限制
https://www.cnblogs.com/mashil/p/6416364.html // 各浏览器Cookie大小、个数限制
https://www.cnblogs.com/YangJieCheng/p/7268378.html // 如何严格限制session在30分钟后过期!
https://www.cnblogs.com/jianqingwang/p/5839151.html // https://www.cnblogs.com/jianqingwang/p/5839151.html //删除与销毁session
PHP: 运行时配置 - Manual // PHP手册 --- 推荐认真阅读
PHP session反序列化漏洞总结 // PHP session反序列化漏洞总结 -- 20210424 周六 公寓
29|Session与Cookie:账户体系的安全设计原理-极客时间 -- 推荐
会话管理 - 弄明白前后端接口 Cookie、Session、Token 的区别
2. 整理输出 2.1 Cookie 1). 简洁介绍
Cookie在远程浏览器端存储数据并以此跟踪和识别用户的机制.
从实现上来说, Cookie是存储在客户端上的一小段数据, 浏览器即客户端, 通过HTTP协议和服务器端进行Cookie交互.
2). Cookie独立于语言存在
也就是说, 不论是PHP还是JSP种下的Cookie, 其本质都是一样的, 客户端脚本JS都能读取到.
Cookie在很多语言中都有实现, 比如 PHP, ASP, Java, .Net. 严格来说, Cookie并不是由这些语言实现的, 而这些语言则是实现对Cookie的间接操作, 即发送HTTP指令, 浏览器收到指令便操作Cookie并返回给服务器.
因此, Cookie是由浏览器实现和管理的.
关于Cookie的RFC文档主要有: RFC6265, RFC2109.
举例来说, 我们经常使用PHP设置Cookie, 但实际上PHP并没有真正地设置过Cookie, 甚至可以说, PHP根本没有能力去设置Cookie. 它只是发出命令让浏览器来做这件事而已, 形象地说就是和"有关部门"打个招呼. 了解这个概念, 对我们后面的学习很重要.
Cookie主要是参照RFC2109标准由客户端实现其生成, 使用等整个管理过程, 服务器端则参考此标准实现和客户端之间的交互指令.
3). 浏览器产生Cookie数量,每个Cookie文件大小
Cookie的总数量没有限制,但是每个域名的Cookie数量和每个Cookie的大小是有
限制的!
IE 每个域名限制为50 个。
Firefox 每个域名Cookie 限制为50 个。
Opera 每个域名Cookie限制为30 个。
Safari/webkit 貌似没有Cookie限制。但是假如Cookie很多,则会使header 大小超过服
务器的处理的限制,会导致错误发生。
不同浏览器间每个Cookie文件大小也不同
Firefox 和safari 是4097 个字节,包括名(name)、值(value)和等号。
Opera 是4096 个字节,包括:名(name)、值(value)和等号。
IE 是4095 个字节,包括:名(name)、值(value)和等号。
Note:
对于这个参数, 其实没那么重要, 毕竟来说是够用的, 另外, 如果需要确切的数据, 请到指定的浏览器官方文档查询确认
随便找一个网站,看Cookie和Sessioin信息 2.2 Session 1). 如何严格限制Session在30分钟后过期!
如何严格限制Session在30分钟后过期? 1. 设置客户端Cookie的lifetime为30分钟; 2. 设置Session的最大存活周期maxlifetime也为30分钟; 3. 为每个Session值加入时间戳,然后在程序调用时进行判断;
Note:
其实, 第二点可有可无, 毕竟第三点已经能确保~
至于为什么,我们首先来了解下PHP中Session的基本原理:
PHP中的Session有效期默认是1440秒(24分钟),也就是说,客户端超过24分钟没有刷新,当前Session就会失效。当然如果用户关闭了浏览器,会话也就结束了,Session自然也不存在了!
大家知道,Session储存在服务器端,根据客户端提供的SessionID来得到这个用户的文件,然后读取文件,取得变量的值,SessionID可以使用客户端的Cookie或者Http1.1协议的Query_String(就是访问的URL的“?”后面的部分)来传送给服务器,然后服务器读取Session的目录. 要控制Session的生命周期,首先我们需要了解一下php.ini关于Session的相关设置(打开php.ini文件,在“[Session]”部分): 1、session.use_cookies:默认的值是“1”,代表SessionID使用Cookie来传递,反之就是使用Query_String来传递; 2、session.name:这个就是SessionID储存的变量名称,可能是Cookie,也可能是Query_String来传递,默认值是“PHPSESSID”; 3、session.cookie_lifetime:这个代表SessionID在客户端Cookie储存的时间,默认是0,代表浏览器一关闭, SessionID就作废……就是因为这个所以Session不能永久使用! 4、session.gc_maxlifetime:这个是Session数据在服务器端储存的时间,如果超过这个时间,那么Session数据就自动删除!
还有很多的设置,不过和本文相关的就是这些了,下面开始讲如何设置Session的存活周期。 前面说过,服务器通过SessionID来读取Session的数据,但是一般浏览器传送的SessionID在浏览器关闭后就没有了,那么我们只需要人为的设置SessionID并且保存下来,不就可以…… 如果你拥有服务器的操作权限,那么设置这个非常非常的简单,只是需要进行如下的步骤: 1, 把“session.use_cookies”设置为1,使用Cookie来储存SessionID,不过默认就是1,一般不用修改; 2, 把“session.cookie_lifetime”改为你需要设置的时间(比如一个小时,就可以设置为3600,以秒为单位); 3, 把“session.gc_maxlifetime”设置为和“session.cookie_lifetime”一样的时间;
在PHP的文档中明确指出,设定Session有效期的参数是session.gc_maxlifetime。
可以在php.ini文件中,或者通过ini_set()函数来修改这一参数。
问题在于,经过多次测试,修改这个参数基本不起作用,session有效期仍然保持24分钟的默认值。 由于PHP的工作机制,它并没有一个daemon线程,来定时地扫描Session信息并判断其是否失效。
当一个有效请求发生时,PHP会根据全局变量session.gc_probability / session.gc_divisor(同样可以通过php.ini或者ini_set()函数来修改)的值,来决定是否启动一个GC(Garbage Collector)。 默认情况下,session.gc_probability = 1,session.gc_divisor =100,也就是说有1%的可能性会启动GC。
GC的工作,就是扫描所有的session信息,用当前时间减去session的最后修 改时间(modified date),同session.gc_maxlifetime参数进行比较,如果生存时间已经超过gc_maxlifetime,就把该session删除。
到此为止,工作一切正常。
那为什么会发生gc_maxlifetime无效的情况呢?
在默认情况下,Session信息会以文本文件的形式,被保存在系统的临时文件目录中。
在Linux下,这一路径通常为\tmp,在 Windows下通常为C:\Windows\Temp。
当服务器上有多个PHP应用时,它们会把自己的session文件都保存在同一个目录中。
同样地,这些PHP应用也会按一定机率启动GC,扫描所有的session文件。
问题在于,GC在工作时,并不会区分不同站点的session。
举例言之
站点A的gc_maxlifetime设置为2小时,
站点B的 gc_maxlifetime设置为默认的24分钟。
当站点B的GC启动时,它会扫描公用的临时文件目录,把所有超过24分钟的Session文件全部删除掉,而不管它们来自于站点A或B。
这样,站点A的gc_maxlifetime设置就形同虚设了。 找到问题所在,解决起来就很简单了。
解决办法:
修改session.save_path参数,或者使用session_save_path()函数,把保存Session的目录指向一个专用的目录,gc_maxlifetime参数工作正常了。
还有一个问题就是,gc_maxlifetime只能保证Session生存的最短时间,并不能够保存在超过这一时间之后Session信息立即会得到删除。因为GC是按机率启动的,可能在某一个长时间内 都没有被启动,那么大量的Session在超过gc_maxlifetime以后仍然会有效。
解决这个问题的一个方法是,把session.gc_probability / session.gc_divisor的机率提高,如果提到100%,就会彻底解决这个问题,但显然会对性能造成严重的影响。
另一个方法是自己使用PHP实现,创建一个Session类,在Session写入时,把过期时间也写入。
读取时,根据过期时间判断是否已过期。// 目前的项目中似乎就是使用这种策略, 同时将Session存储在Redis中
demo.php
class Session{ /** * 设置session * @param String $name session name * @param Mixed $data session data * @param Int $expire 超时时间(秒) */ public static function set($name, $data, $expire=600){ $session_data = array(); $session_data['data'] = $data; $session_data['expire'] = time()+$expire; $_SESSION[$name] = $session_data; } /** * 读取session * @param String $name session name * @return Mixed */ public static function get($name){ if(isset($_SESSION[$name])){ if($_SESSION[$name]['expire']>time()){ return $_SESSION[$name]['data']; }else{ self::clear($name); } } return false; } /** * 清除session * @param String $name session name */ private static function clear($name){ unset($_SESSION[$name]); } }
session_start(); $data = '123456'; session::set('test', $data, 10); echo session::get('test'); // 未过期,输出 sleep(10); echo session::get('test'); // 已过期
2). 删除与销毁Session
PHP学习笔记:删除与销毁Session- 简庆旺 - 博客园
3). 关于Session的存储和PHP的获取 sess_8kk3uhek69qc1qd2asmhdbeu1i 在docker容器中的文件形式
__flash|a:1:{s:11:"postDeleted";i:-1;}captcha|O:11:"ArrayObject":4:{i:0;i:0;i:1;a:2:{s:6:"number";i:5;s:8:"lifetime";i:3600;}i:2;a:0:{}i:3;N;}captcha.number|i:5;captcha.lifetime|i:3600;postDeleted|s:40:"You have successfully deleted your post.";__id|s:3:"100";__authKey|s:10:"test100key";
这里存储的数据都是写入的测试数据,序列化后存储。
网页请求头中的cookie中sessionid 可以看到,key为PHPSESSID, value就是sessionid, 跟存储在服务器上的文件名有前缀区别,这只是服务的设置而已,依然能定位到某个会话的文件和信息 以及后端PHP获取的sessionid 额外,提醒一点:
即便是同一个用户,每次登陆,都是重新生成一个sessionid, 只要保证每次有的用就好了,而且相对来说更加安全。
后续补充 ... |