多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## session ![](http://cdn.aipin100.cn/18-4-12/67940155.jpg) ### 做某事之前要先确保一些东西 [framework/Session.php at master · top-think/framework](https://github.com/top-think/framework/blob/master/library/think/Session.php) 很多方法中使用了: ```php empty(self::$init) && self::boot(); ``` 这是保证操作前session是开启的: ```php // init()方法代码段 if ($isDoStart) { session_start(); self::$init = true; } else { self::$init = false; } ``` 既然这样,很多方法都用到了,重复写不是很好,我们将它单独写到一个方法里面: ```php // 确保进行操作前session是开启并准备好的 private function _ensure() { empty(self::$init) && self::boot(); } ``` > 这种例子很多地方都有,比如sql操作检查数据库连接那里也是一样,也可以这样做,保证操作前数据连接是准备好的,可用的。(已经是这样做的了: `$this->initConnect(true);`) * * * * * ### 不能忽视的问题 ```php /** * 暂停session * @return void */ public static function pause() { // 暂停session session_write_close(); self::$init = false; } ``` 注意 `self::$init = false;` 这个细节很重要,说明 `session_write_close()` 是停止了session的。 session操作必须要对文件进行读写锁,保证此时其他进程不能读和写,这是很重要的,因为如果不这样的话很可能会出现 **“更新丢失”** 的问题。 **所以在使用其他session驱动时也要注意这个问题,`read()` 方法也要保证行锁,否则就会有问题,但如果和加锁的话,又会出现多页面session阻塞的老问题了,传统文件方式就是因为文件锁的原因造成的多页面阻塞。** (最好不要使用MySQL,行锁需要开启事务,这可能会引起事务嵌套等一些问题)redis驱动的read()没有使用行锁,那么其实也会有更新丢失的问题的。**(其实就算出现更新丢失,数据不同步等问题,也没事,因为出现的问题就是,session数据变成竞态资源了,当没有锁时,后果要看《并发问题带来的后果》,一般重要数据也不会放在session里面,所以就算出问题,也只是验证码验证结果不同步等问题,明明图片不对,但是显示验证结果正确,这是因为点击切换图片太快了,导致验证时取的是旧数据)** > session只在启动时open数据源(文件或数据库,打开独占文件,或者连接数据库),并读取read数据,然后写入`$_SESSION`全局变量中。默认情况下,只读这一次,每启动session_start()一次就会读取一次数据。 另外当你使用 `session_write_close()` 时要确定你之后不会再进行session操作了,一定要在所有的session数据修改保存结束后再调用它,否则之后再直接使用 `$_SESSION['S'] = 1;` 这样就不会保存数据哦,因为session已经被关闭了,如果使用tp的`session()`函数就不会,原因你也看到了,它做了处理。 [MySql中的事务嵌套 - 小小的博客大大的世界 - 博客园](https://www.cnblogs.com/tongx/p/4936253.html) [PHP中实现MySQL嵌套事务的两种解决方案 - CSDN博客](http://blog.csdn.net/hello_katty/article/details/45220825) * * * * * [基于 Token 的 WEB 后台认证机制](https://mp.weixin.qq.com/s/QDr4DaMrH-g78l5oXFfbeg) > tp支持session_id参数指定在url上,但是这种其实还是传统的 `cookie - session` 模式,如果简单的将这个cookie叫做token的话,那么没什么意义,不过是session_id换个名字而已。所以 token ≠`cookie - session` ,token和session是不同的技术方案。 [聊一聊HTTP会话管理](https://www.toutiao.com/a6537805588791820813/?tt_from=weixin&utm_campaign=client_share&timestamp=1522255724&app=news_article_lite&utm_source=weixin&iid=25315997380&utm_medium=toutiao_android&wxshare_count=1) [小白科普:“无状态”那点事儿](http://mp.weixin.qq.com/s/7KmEOXhefUxv51rR03SarA) [php - 基于 session 和基于 token 的用户认证方式到底该如何选择? - SegmentFault 思否](https://segmentfault.com/q/1010000008691659) [<转> session、cookie、token详解 - PHP程序痴-妖都小陈 - 博客园](https://www.cnblogs.com/gzchenjiajun-php/articles/4895394.html) [session fixation攻击 - CSDN博客](https://blog.csdn.net/wauit/article/details/47402125) [Session,Token相关区别 - 骑着乌龟去看海 - 博客园](https://www.cnblogs.com/xiaozhang2014/p/7750200.html) > Token就不会在服务器上存储数据了,数据加密、签名后生成一个唯一的Token。 [3 种 Web 会话管理的方式](http://mp.weixin.qq.com/s/0EqNx5YqmK63om8-FpzPvA) > Token方式,Token是登录信息加密的字符串(用户ID,),如果服务端信息变化(用户名,类似session信息),那么每次Token也会改变啊,而session就没有这个问题,看来就要撇弃session思维,忘掉session上下文环境,这些信息要另外想办法,不能放在登录信息里面,保持登录信息的干净,这样Token就不会变了,既然不使用session了,那么就要彻底放下,不能还保留着那种思想,要是只是换个名字,还是旧思想,换汤不换药就没有意义。 > > **session方式也相当于是提供上下文环境,比如验证码,比如业务操作执行到哪一步都可以记录在session中,很方便,如果不用session,那么业务就不能使用这种方式了,可以放在一个表中实现一样的效果。** > > 安全:session方式其实不存在安全问题,登录时可以记录用户的登录环境,IP,设备信息等,过期时间,这样当用户环境发生改变可以让其重新验证。(登录状态不能仅是一个状态,登录状态:正常,过期,环境改变,其它);Token:不能把凭证直接放到url后面进行传递,坏人通过Reffer header可以窃取。 [JSON Web Tokens - jwt.io](https://jwt.io/#libraries-io) [php JWT在web端的使用方法 - 个人文章 - SegmentFault 思否](https://segmentfault.com/a/1190000009981879) [前后端分离, JWT 还是 Oauth2? - V2EX](https://www.v2ex.com/amp/t/439613) [你可能并不需要 OAuth2 | mdluo's blog](https://mdluo.com/2018-02-11/you-may-not-need-oauth2/) [基于Token的身份验证——JWT - ChrisZZ - 博客园](https://www.cnblogs.com/zjutzz/p/5790180.html) [手把手教会你小程序登录鉴权](http://mp.weixin.qq.com/s/WIM7M5RRWDfZHVq6zwmNSA) [OAuth 2.0是什么?看这篇文章就够了](https://mp.weixin.qq.com/s/tAZQm-gF3oLHfE_x_U1xVw) [JSON Web Token - 详解](https://www.toutiao.com/a6494101429945369101) > session时可以储存一些**用户上下文数据**,比如业务中,提交过程的哪一步,等等,我们可以在session存储一些有用的数据,那么现在这个,这些数据难道放在有效载荷种储存吗,肯定不行吧,如果放到载荷中,上下文数据是经常变动的,那么每次生成的令牌都不一样,肯定不行啊,感觉非常不方便!明明session好好的,为什么非要搞个这么麻烦的东西出来,说在无cookie的环境下不友好,简直是睁眼说瞎话,session_id不也可以放在url或者提交参数中,跟这个不是不就是一样的!!! > > 这个主要是判断用户的登陆状态的,可能你还没有涉及到集群和分布式的东西,没有太理解了里面的东西,这个东西很多大公司都在使用,必然有它的可取之处 [如何使用JWT向服务器证明你就是你](https://mp.weixin.qq.com/s/BmQ-r7rf5tq3rNahEvSgKg) > JWT载荷里面信息有限,不能像session中那样保存很多业务数据在服务器上,比如在用户session存储当前操作进行到哪一步,验证码,业务数据,等等这样的用户上下文信息,要知道这类场景是很多的,很多这样的信息会放在session中,你JWT没有session了,那怎么处理这些的情况呢? > > 传统的基于session网站后台等等,可以改造吗,如果可以,怎么解决我上面说的问题? > > JWT用于用户认证的情况比较多,在用户认证中token中可以存储userId这种不变的数据。像那种实时性比较高或者业务逻辑相关的数据不太适合使用JWT,一来数据一变就需要更新token,二来将业务逻辑相关的数据放在token中也存在安全性问题。 [JSON Web Token 入门教程 - 阮一峰的网络日志](http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html) > 不加密的JWT相当于是将原来服务端的session信息交给客户端存储了,t由服务端生成,用签名来保证载荷信息不能被篡改,所以是可靠的。但注意在载荷信息是透明的,所以不能存入私密信息,除非对t加密传输。 > > 如果载荷每次信息改变了,那么t也会改变,也就是同时有多个t生效为有效验证了(除非服务器在颁发和验证时部署额外的逻辑)。jwt是一种认证机制,不再有登录状态和在线的概念了,这点是和session最大的区别。 [使用 Cookie 实现公有云会话跟踪](https://www.ibm.com/developerworks/cn/web/wa-session-tracking-using-cookies/index.html) 多个浏览器tab 同时访问一个网站,服务器如何区分不同 tab? > 传统是 一个浏览器 对应一个 key,对应一个用户 > 现在是 一个浏览器还是对应一个 key ,但不是对应一个用户,而是可以对应多个登录用户(或者是多个key也可以,文中的实现方式就是这样的) [HTTP API 认证授权术 | | 酷 壳 - CoolShell](https://coolshell.cn/articles/19395.html) [JWT攻击手册:如何入侵你的Token](https://mp.weixin.qq.com/s/BH-gmMpHUkMvBcSBgJWnwA) [单点登录系统原理与实现,图文并茂,附源码](https://mp.weixin.qq.com/s/EH_gGn8X8KbL71INGym6sQ) [浅析 JWT](https://mp.weixin.qq.com/s/wVYMUWsGKTUP_H5hGvoPKQ) [稳了!这才是cookie,session与token的真正区别](https://mp.weixin.qq.com/s/X0F1xE7MwKM-TIXZs4GWcw) [Web 安全之 XSS](https://mp.weixin.qq.com/s/V9HXB8FOxBed0qqJfFSJjQ) [开发工具箱 - JWT 在线解密](https://www.box3.cn/tools/jwt.html) > JWT 中的数据是明文的,它只是保证数据不会被篡改(尾段为前两段的签名),所以JWT 最主要的作用就是云端无存储的验证方案。核心理念是无存储验证。 * * * * * ### 单点登录 [php - session多端登陆,共享怎么做的啊? - SegmentFault 思否](https://segmentfault.com/q/1010000005788476) [单点登录原理与简单实现](http://mp.weixin.qq.com/s/FDI35yvHFhpET-xU0kHEHw) 同主域的多系统,其实不需要单点登录,直接cookie设置为一级域名就可以了,这样各个二级域下都有效果。当多个系统的主域名不同时才需要使用单点登录,比如百度和hao123和糯米。 [单点登录原理与简单实现](https://mp.weixin.qq.com/s/89YtsPX4cPLluWbM8JSNXQ) [微软首席信息安全官:我们为什么不需要密码](https://mp.weixin.qq.com/s/lasTD9j6S1TuXCB8X3w90g) [JSON WEB TOKEN从原理到实战](https://mp.weixin.qq.com/s/wMi-VSlGTWCZQqRc521GqA) [扫码登录实现原理](https://mp.weixin.qq.com/s?__biz=Mzg3NTExMTg2Mw==&mid=2247484666&amp;idx=1&amp;sn=996db3b1a9c0fc7ca23fbad09483fd18&source=41#wechat_redirect) [微信多点登录,消息漫游,假如让你来实现?](https://mp.weixin.qq.com/s/gHnq-VqRSBX-UiGd306NDw) [对 Session 的深入探讨](https://mp.weixin.qq.com/s/Koto-w9U9mt8H1zZW2ETZQ) 没有seseion时用 上下文表,uid,上下文json [看完这篇 Session、Cookie、Token,和面试官扯皮就没问题了](https://mp.weixin.qq.com/s/-Zlviajdw_I1xzbhznflKw) [究竟如何保证session一致性?](https://mp.weixin.qq.com/s/hCrcboJ6CHe8qlg-fv4T0A) > session相当于缓存,传统文件session要阻塞就是防止多请求并发问题,所以会话过程锁文件,如果用别的就会有更新丢失脏数据等不一致问题,所以记住sessiin只是缓存,如果要保证数据一致性就不应该依靠session了,只要记住它只是一般的缓存就行了。 [tuupola/branca-php](https://github.com/tuupola/branca-php) 比jwt更安全 [单点登录那些事儿(三)不同域下的单点登录 - 开发者交流中心 / 认证协议交流 - Authing 论坛](https://forum.authing.cn/t/topic/120) * * * * * ### session注意的问题 如果在登录环境中是无法顺利做上面的实验的哦,因为在同一浏览器上面登录时,session多页面文件阻塞问题。参考:[PHP中Session引起的脚本阻塞问题解决办法](http://www.jb51.net/article/48805.htm) thinkphp中想要提升性能在使用完session后需要及时的执行: ```php // 及时暂停session,释放session文件,可以避免发生多页面session阻塞问题 // 不这样做的话,对于用户来说,统一发起的多个请求,如果其中一个请求相应慢也会影响其他请求 // 最好不使用文件储存session,使用其他无锁的缓存,不过没有锁的话,还有面对两次会话可能出现的数据不一致和并发修改数据的问题 Session::pause(); ``` 这样多页面访问时就会感觉到显著的速度提升。 ***** last update:2018-11-6 04:44:17