## 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×tamp=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&idx=1&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
- 开始
- 公益
- 更好的使用看云
- 推荐书单
- 优秀资源整理
- 技术文章写作规范
- SublimeText - 编码利器
- PSR-0/PSR-4命名标准
- php的多进程实验分析
- 高级PHP
- 进程
- 信号
- 事件
- IO模型
- 同步、异步
- socket
- Swoole
- PHP扩展
- Composer
- easyswoole
- php多线程
- 守护程序
- 文件锁
- s-socket
- aphp
- 队列&并发
- 队列
- 讲个故事
- 如何最大效率的问题
- 访问式的web服务(一)
- 访问式的web服务(二)
- 请求
- 浏览器访问阻塞问题
- Swoole
- 你必须理解的计算机核心概念 - 码农翻身
- CPU阿甘 - 码农翻身
- 异步通知,那我要怎么通知你啊?
- 实时操作系统
- 深入实时 Linux
- Redis 实现队列
- redis与队列
- 定时-时钟-阻塞
- 计算机的生命
- 多进程/多线程
- 进程通信
- 拜占庭将军问题深入探讨
- JAVA CAS原理深度分析
- 队列的思考
- 走进并发的世界
- 锁
- 事务笔记
- 并发问题带来的后果
- 为什么说乐观锁是安全的
- 内存锁与内存事务 - 刘小兵2014
- 加锁还是不加锁,这是一个问题 - 码农翻身
- 编程世界的那把锁 - 码农翻身
- 如何保证万无一失
- 传统事务与柔性事务
- 大白话搞懂什么是同步/异步/阻塞/非阻塞
- redis实现锁
- 浅谈mysql事务
- PHP异常
- php错误
- 文件加载
- 路由与伪静态
- URL模式之分析
- 字符串处理
- 正则表达式
- 数组合并与+
- 文件上传
- 常用验证与过滤
- 记录
- 趣图
- foreach需要注意的问题
- Discuz!笔记
- 程序设计思维
- 抽象与具体
- 配置
- 关于如何学习的思考
- 编程思维
- 谈编程
- 如何安全的修改对象
- 临时
- 临时笔记
- 透过问题看本质
- 程序后门
- 边界检查
- session
- 安全
- 王垠
- 第三方数据接口
- 验证码问题
- 还是少不了虚拟机
- 程序员如何谈恋爱
- 程序员为什么要一直改BUG,为什么不能一次性把代码写好?
- 碎碎念
- 算法
- 实用代码
- 相对私密与绝对私密
- 学习目标
- 随记
- 编程小知识
- foo
- 落盘
- URL编码的思考
- 字符编码
- Elasticsearch
- TCP-IP协议
- 碎碎念2
- Grafana
- EFK、ELK
- RPC
- 依赖注入
- 开发笔记
- 经纬度格式转换
- php时区问题
- 解决本地开发时调用远程AIP跨域问题
- 后期静态绑定
- 谈tp的跳转提示页面
- 无限分类问题
- 生成微缩图
- MVC名词
- MVC架构
- 也许模块不是唯一的答案
- 哈希算法
- 开发后台
- 软件设计架构
- mysql表字段设计
- 上传表如何设计
- 二开心得
- awesomes-tables
- 安全的代码部署
- 微信开发笔记
- 账户授权相关
- 小程序获取是否关注其公众号
- 支付相关
- 提交订单
- 微信支付笔记
- 支付接口笔记
- 支付中心开发
- 下单与支付
- 支付流程设计
- 订单与支付设计
- 敏感操作验证
- 排序设计
- 代码的运行环境
- 搜索关键字的显示处理
- 接口异步更新ip信息
- 图片处理
- 项目搭建
- 阅读文档的新方式
- mysql_insert_id并发问题思考
- 行锁注意事项
- 细节注意
- 如何处理用户的输入
- 不可见的字符
- 抽奖
- 时间处理
- 应用开发实战
- python 学习记录
- Scrapy 教程
- Playwright 教程
- stealth.min.js
- Selenium 教程
- requests 教程
- pyautogui 教程
- Flask 教程
- PyInstaller 教程
- 蜘蛛
- python 文档相似度验证
- thinkphp5.0数据库与模型的研究
- workerman进程管理
- workerman网络分析
- java学习记录
- docker
- 笔记
- kubernetes
- Kubernetes
- PaddlePaddle
- composer
- oneinstack
- 人工智能 AI
- 京东
- pc_detailpage_wareBusiness
- doc
- 电商网站设计
- iwebshop
- 商品规格分析
- 商品属性分析
- tpshop
- 商品规格分析
- 商品属性分析
- 电商表设计
- 设计记录
- 优惠券
- 生成唯一订单号
- 购物车技术
- 分类与类型
- 微信登录与绑定
- 京东到家库存系统架构设计
- crmeb
- 命名规范
- Nginx https配置
- 关于人工智能
- 从人的思考方式到二叉树
- 架构
- 今日有感
- 文章保存
- 安全背后: 浏览器是如何校验证书的
- 避不开的分布式事务
- devops自动化运维、部署、测试的最后一公里 —— ApiFox 云时代的接口管理工具
- 找到自己今生要做的事
- 自动化生活
- 开源与浆果
- Apifox: API 接口自动化测试指南