【PHP】深入理解PHP的session。
来源:互联网 发布:哥伦比亚大学 知乎 编辑:程序博客网 时间:2024/06/05 14:44
一、具体session是用来干嘛的。
这里不详细举例,可以看文章:http://www.cnblogs.com/wangtao_20/archive/2011/02/16/1955659.html。
二、$_SESSION到底是怎么存储的。
2.1、php.ini配置解析。
$_SESSION这个变量可以存在文件中、可以存在redis\memcache中,主要看你的设置。
下面讲述的所有逻辑都是基于$_SESSION存储在memcache中(也就是下面的所有逻辑讲述都是基本本人项目的配置)。
在php.ini中有如下配置:
从上面的配置中,我们可以知道,save_handler是memcache,使用cookie,而且cookie的key是PHPSESSID。gc_maxlifetime=7200。
我们在PHP服务端写下如下代码,通过打印session_name()可以知道session的cookie的key = PHPSESSID。至于为啥session要借助于
cookie,这里不描述,请大家自行搜索。
public function forTest() { echo session_name();// 打印结果 = PHPSESSID exit(); }
2.2、PHPSESSID是啥,我们从哪里看PHPSESSID,这个cookie的value是如何生成的。
在chrome浏览器,F12模式下,可以看到如上红框所示的cookie。
2.3、我们怎么获取$_SESSION的值。
通过在PHP中,我们打印$_SESSION,我们可以知道存储在memcache中的值格式如下所示。
其中有个key = user_info,因为,我用user_info这个key来存储了用户的登录信息。
/** { user_info: { uid: "1", user_name: "gz****", token: "06d9618a69891019000748b81577a7db", staff_name: "**", login_time: "2017-08-26 15:50:04", login_ip: "10.1.102.31" } }*/ exit(json_encode($_SESSION));
我门使用另外一种方式来获取这个值,因为我们知道了这个值是存储在memcache中的,那么我们可以直接通过memcache的
接口来获取这个值。下面的值是序列化的结果,具体关于PHP序列化的也有一些坑点,http://blog.spoock.com/2016/10/16/php-serialize-problem/。
具体的坑点就是使用不同的引擎结果会不一样。
$key = $_COOKIE[session_name()];/** * user_info|a:6:{s:3:"uid";s:1:"1"; * s:9:"user_name";s:6:"gz****"; * s:5:"token";s:32:"06d9618a69891019000748b81577a7db"; * s:10:"staff_name";s:6:"**"; * s:10:"login_time";s:19:"2017-08-26 15:50:04"; * s:8:"login_ip";s:11:"10.1.102.31";}*/$str = PubCache::memcache('default', $key);
总结:
(1)从上面我们可以知道,PHP默认的session存储方式是,当会话开始(session_start())时,通过前端浏览器传输过来的域名、
浏览器的标志等其他参数加密后得到一个值,我们称这个值是PHPSESSID_VALUE,相应的key = PHPSESSID。
(2)很明显这个值,与浏览器相关(大家可以自行测试)、与时间相关,与登录的用户名其实无关的(因为此时PHP还不知道所谓登录的用户名)。
PHP知道PHPSESSID_VALUE这个值后,PHPer可以通过$_SESSION[$key]来设置不同的值。在memcache中的存储本质就是:
PHPSESSID_VALUE: {
'key1' : {...},
'key2': {...},
}
比如,如果key1 = 'user_info',你就可以用来存储用户当前的登录信息。
然后向前端发送cookie。set_cookie('PHPSESSID', PHPSESSID_VALUE, ...);
我们每次通过前端发送过来的cookie,先索引到PHPSESSID这个key对应的cookie值,然后通过对应值,就可以去缓存里查到相应的数据了。
2.4、上面的模式存在很多问题。
(1)memcache会存在内存不够的问题,所以对于用户量很大的站点,要多分配该memcache进程内存;
(2)前端浏览器可能设置不支持cookie;
(3)无法做到单机登录,因为不同的浏览器PHPSESSID对应的值不一样,也即是,你在chrome浏览器上退出后,在ie浏览器上还是登录的。
三、各种session相关的需求。
3.1、原本用户在线时长最多是2h,现在想改为30天。
首先,需要在php文件的执行入口执行如下代码。要在session_start()之前(必须在此之前)改变session.cookie_lifetime、session.gc_maxlifetime的生存时间。
define('SESSION_TIME', 2592000);ini_set('session.cookie_lifetime', SESSION_TIME);ini_set('session.gc_maxlifetime', SESSION_TIME);session_start();
再次,为了保证,还需要在设置$_SESSION时,再次设置。
if ( !isset($_SESSION) ) { ini_set("session.cookie_lifetime", defined('SESSION_TIME')?SESSION_TIME:7200); ini_set("session.gc_maxlifetime", defined('SESSION_TIME')?SESSION_TIME:7200); session_start();//判断session是否开启 } if ( isset($value) ) { $_SESSION[$key] = $value;//设置session return true; } else { return isset($_SESSION[$key]) ? $_SESSION[$key] : '';//取得session }
就是我们在设置$_SESSION时,首先判断该变量是否存在,然后设置。
3.2、实现单一设备的登录。
当user_name = A(在系统中用户名肯定是唯一的)的用户在chrome上登录后,此时我们就要记录下用户名、PHPSESSID的对应关系。1H后
当user_name = A用户换成在ie浏览器上登录,此时应该通过用户名去检查上一个PHPSESSID,并将上一个PHPSESSID对应memcache中的
数据清理掉,然后再存储目前的PHPSESSID。
这样,就可以实现单一设备登录。
3.3、实现主动T用户下线。
(1)直接通过用户的user_name对应的几个PHPSESSID(假设可以多客户端登录,这个事先存储在缓存或者mysql中)。
去清除这些PHPSESSID对应的缓存。但是,这样无法清除掉前端的cookie。需要用户下一次访问接口时,如果检查到服务端
已经清除掉session的缓存了,再次set_cookie()设置过期来清除掉前端的cookie。
(2)因为考虑到用户可以多浏览器登录的问题,所以每次用户登录时,要根据其user_name当作key,记录下此时的PHPSESSID。
当每当系统主动T除用户下线时,给该用户在后端的缓存中设置一个标记。每当这个用户不管在哪个浏览器下一次访问时,先检查
此时的PHPSESSID,如果此PHPSESSID对应的session还存在,则在服务端执行session_destroy();可以同时清除存储在服务端的
session和客户端的cookie。当某个用户所有的PHPSESSID都清除完成后,就可以在缓存中清除掉这个标记了。标记在缓存中的记录,
要合理分配过期时间,以及合理延长过期时间。这样逻辑才严谨。
但是,以上所有的方式都有个问题,就是需要用户下次访问时,去检查,才可以正式知道。
(3)当然了,对于一般长在线的系统(比如在线游戏)。都是保留了一个socket与服务端进行通信。每当心跳的时候去检查,可以做到实时T除该用户
下线。不过当系统做T除下线操作时,此时该用户没有开启该页面的话,也需要他下次访问时,才会实时T除。这些都是WEB与客户端实时在线,完全
不同的地方。
也就是说,我们考虑这个问题时,不仅仅要考虑同时清除cookie、后端缓存(如果是存在文件里,就是清除文件),也要考虑当前用户是否打开了页面。
如果当前没有打开页面,下次该用户访问页面时如何处理。还要考虑用户可以在多个浏览器上访问的因素。
3.4、用户在选购商品时,不需要登录。
我们浏览京东商城、天猫时,可以在不登录的情况下选购商品加入购物车,并且下次进来还有。只是当我们去支付的时候,才会提示登录。
这种,用session很好实现。当用户选购时,直接将用户选购的商品放入session中,直到他登录后,再从session中转移到mysql中。
四、其他语言的session的实现,或者是我们自己实现。
4.1、从上面,我们可以知道,PHP默认是有一套session的实现机制,而且在底层也封装了session_id的实现,
而且封装了变量$_SESSION等。我们除了使用PHP默认的实现方式外,就无其他办法了吗。
可以搜索关键字 PHP 、session_set_save_handler来查询相关资料。http://www.cnblogs.com/xingmeng/p/3223043.html。
这篇文章也介绍他自己写的处理机制。也可以上github上搜索相关的文章。
4.2、其他语言也有自己的实现方式。
比如,我们经常听到token来实现用户的登录。所谓token也就是服务端根据用户名、客户端标记、时间以及一定的算法来生成的value。
然后每次发送服务端时,都带上这个token。类似的就是移动客户端开发(非web),我们怎么实现类似于浏览器session机制呢。
就可以采用token的方式。其实,这个token就是类似于上面的PHPSESSID,只是这个值,需要我们自己来实现。
token与cookie有哪些异同呢。
(1)两者都是在http传输过程中,带到服务端去;
(2)两者都可以加密生成;
(3)两者都可以设置过期时间;
(4)但是cookie存储在cookie中,容易xss攻击,token可以存储在 client-side 中的 cookie 或 localstorage(数据库);
token的这种思维,可以不仅仅应用在web中,也可以应用在其他需要认证的逻辑中。
比如在微信公众号开发、jenkins的开发中,会发现很多权限验证时,都使用了token。比如接口调用权限、整个用户的验证权限等。
而且这些token还可以设置过期时间,以及具体应用的粒度,就看你的需求和实现方式了。
- 【PHP】深入理解PHP的session。
- 深入理解PHP的Session机制
- 深入理解PHP中的SESSION技术
- php 的SESSION的理解
- php中session的理解
- PHP Notice: session_start(): ps_files_cleanup_dir-深入理解PHP原理之Session Gc的一个小概率Notice
- php session深入讲解
- 深入理解PHP原理之Session Gc的一个小概率Notice
- 深入理解PHP原理之Session Gc的一个小概率Notice
- 彻底理解PHP的SESSION机制
- 彻底理解PHP的SESSION机制
- 彻底理解PHP的SESSION机制
- 彻底理解PHP的SESSION机制
- 彻底理解PHP的SESSION机制
- 彻底理解PHP的SESSION机制
- 彻底理解PHP的SESSION机制
- 彻底理解PHP的SESSION机制
- 【转】彻底理解PHP的SESSION机制
- shell常用代码
- css中position的详细介绍
- 【题解】2006 能量项链(P1063)
- java jar的解释
- 改写ui-grid headerCellTemplate
- 【PHP】深入理解PHP的session。
- C#跨窗体传值的几种方法分析(很详细)
- 使用ARM芯片的小型NAS设备的一次存储故障的检修
- 最大连续子数组的和(记录子数组范围)
- Dubbo-Admin管理平台和Zookeeper注册中心的搭建
- JavaScript 懒加载图片
- Python爬虫利器之Beautiful Soup的用法
- FFT入门
- 达人篇:3.2)零缺陷管理法;