- cookie
- cookie认识
- cookie优点
- cookie缺点
- cookie常用方法
- session
- session认识
- session的过期时间
- session优点
- session缺点
- session的使用方法
- 测试
- Local Storage
- Session Storage
- cookie,Local Storage,Session Storage的对比
cookie
cookie认识
Cookie英文是曲奇饼、小甜品的意思。Cookie存放在客户端,通常需要与后台进行交互,后台设置cookie,然后存放在客户端,在客户端保存的是字符串,如下
cookie常用于网站的用户登录,将用户id存放到cookie中(用户id得加密),每次请求其他api时判断该cookie是否存在,如果存在则用户已登录,如果不存在则代表用户没有登录。
要知道,cookie必须在同一网站
下且cookie的path路径为当前url或者是当前url的父级时
才是共享的,具体内容看我下篇文章。
cookie分为俩种
- 第一种:cookie没有设置过期时间
setcookie('userId','4343');
如果是未设置过期时间的cookie,那么用户只要关闭浏览器
(注意是关闭浏览器是不是关闭标签页)就会清除该cookie,并不会保持客户端状态
。这种cookie也可以叫做session类的cookie,session顾名思义就是会话控制
,则说明该cookie只在本次会话中有效,下次会话则会销毁。
由于不能保持客户端状态,所以如果使用这种登录方式的话,用户只要退出浏览器就得重新登录
为了验证,我们做以下测试
1.随便定义一个接口,接口内容如下
public function index(Request $request)
{
setcookie('userId','4343');
dd($_COOKIE['userId']);
}
浏览器访问如下
2.屏蔽代码中的setcookie
public function index(Request $request)
{
//setcookie('userId','4343');
dd($_COOKIE['userId']);
}
我们关闭退出
浏览器,重新访问上述接口,发现userId这个cookie已经不存在,随着关闭浏览器而销毁了
- 第二种:cookie设置了过期时间
setcookie('userId','4343',time()+3600);
如果是设置了过期时间的cookie,那么该cookie是存在物理内存
中,也就是关闭浏览器后该cookie并不会被删除,只有该cookie过期后才失效。也就是说重新打开该网站后,还可以重新获取到该cookie(未过期的前提下)。可以看到该cookie的expires此时为过期时间而不是第一种不设置过期时间时显示的session
由于这种方式是可以保持客户端状态的,所以如果使用这种登录方式的话,用户在关闭浏览器后,重新打开时,如果cookie没有过期的前提下,用户时仍然保持登录状态的的。
我们看到幕课网登录时有一个7天内自动登录
的选项,选中登录之后在7天内是可以保持登录状态的,此处就是设置cookie在7天后过期,使用的是我们第二种
方式。而如果不选中的话,退出浏览器后再次进入时需要重新登录,使用的是我们第一种方式
为了验证是否能保持客户端状态,我们同样做以下实验
1.随便定义一个接口,接口内容如下
public function index(Request $request)
{
setcookie('userId','4343',time()+3600);
dd($_COOKIE['userId']);
}
浏览器访问如下
2.屏蔽代码中的setcookie
public function index(Request $request)
{
//setcookie('userId','4343');
dd($_COOKIE['userId']);
}
我们关闭退出
浏览器,重新访问上述接口,发现userId这个cookie仍然存在,仍然可以访问,并没有随着浏览器的关闭而销毁
cookie优点
- 设置带过期时间的cookie,此cookie不会因会话结束或者客户端关闭而销毁,可以
保持客户端状态
。而session则没有该功能。
cookie缺点
- Cookie因为是暴露在客户端的,所以相对不安全,容易被盗取,泄露个人隐私,如果必须存放cookie的话必须得加密;
- Cookie数量控制在20个以内,每个cookie值的大小控制在4kb以内,而且每次都会携带在http头里面,如果cookie保存过多会带来性能损耗,为了解决这个问题我门可以使用下面介绍的
local Storage
- Cookie必须依赖于客户端,客户端(浏览器)如果关闭Cookie,则无法使用cookie。慕课网登录同样是使用cookie,如果禁用cookie之后,提示登录异常
cookie常用方法
- 创建cookie
//建议使用第一种
setcookie('userId','4343',time()+3600);
//使用$_COOKIE赋值时,该cookie不会在控制台中的cookie显示且不能设置过期时间
$_COOKIE['userId']=4343
- 修改cookie
同创建cookie - 查询cookie
//查询所有cookie
$_COOKIE
//查询单独cookie
$_COOKIE['userId]
- 删除cookie
setcookie('userId','',time()-1);
session
session认识
session上面已经说了,顾名思义为会话
。只有同一会话
内的session才会共享。
那么怎么判定是同一会话呢?答案就是:session_id
,后台可通过查看session_id()函数获取值,也就是说同一个session_id
的session才会共享。
那么session_id又是什么呢?看下php.ini中的这段配置,大概可以知道session_id默认是一个名为PHPSESSID的cookie,session实现需要依赖cookie。
; Whether to use cookies.
; http://php.net/session.use-cookies
session.use_cookies = 1
; Name of the session (used as cookie name).
; http://php.net/session.name
session.name = PHPSESSID
session的过期时间
通过上面的介绍可以知道session共享的决定性因素是同一个session_id,而session_id是客户端存储的一个cookie,而cookie又可以设置过期时间,那么换种方式说:session其实也是可以设置过期时间的,本质是给session_id设置过期时间即可。
以下是php.ini中一段配置:
; Lifetime in seconds of cookie or, if 0, until browser is restarted.
; http://php.net/session.cookie-lifetime
session.cookie_lifetime = 0
可以看到session.cookie_lifetime默认为0
,其实就是指session_id的cookie有效期直到下次浏览器重新打开,也就是该cookie属于session级别的,下次打开浏览器session_id是重新生成的,上次存储的所有session将不能访问。
如果想要设置session过期时间,本质其实是设置session_id的cookie有效期即可,只需要修改php.ini中参数session.cookie_lifetime值大于0即可。
在laravel中可以很方便的设置,不需要直接修改php.ini,只要修改session.php中的lifetime参数即可。
'lifetime' => env('SESSION_LIFETIME', 120),
我们可以看到在laravel中session_id的cookie默认为laravel_session
而不是下面的PHPSESSID,而且exprise设置了到期时间,不是session了。
session是和session_id关联的,不同的会话会产生不同的session_id,只有在同一sesssion_id的情况下,才会共享存储的session,不同session_id下存储的session是不能互相查询获取的。
Session在PHP中使用前必须开启session,函数是session_start()。在laravel可以放到web中间件里,web中间件实现了session_start()。
session驱动类型
cookie是存放在客户端的,而session是存放到服务器端
的。看下面php.ini中的一段配置
; Handler used to store/retrieve data.
; http://php.net/session.save-handler
session.save_handler = files
; Argument passed to save_handler. In the case of files, this is the path
; where data files are stored. Note: Windows users have to change this
; variable in order to use PHP's session functions.
;
; The path can be defined as:
;
; session.save_path = "N;/path"
可以看出服务端的session数据默认是存储到file中的,其实session的驱动类型有如下几种
- file : 默认选择方式。
- database: Sessions 被存储在关系型数据库中
- memcached / redis - Sessions 被存储在基于高速缓存的存储系统中。
- cookie - Sessions 被存储在安全加密的 cookie 中。
在laravel中可以直接修改session.php文件中的环境变量SESSION_DRIVER
来控制session使用哪种驱动。
比如我们使用来redis驱动,设置下面3个session
session(['mm'=>'aa']);
session(['kk'=>'bb']);
session(['cc'=>'ff']);
我们可以看看redis中是怎么存储这个3个数据的呢?
local:2>keys *
1) "laravel_cache:nOz7DwByMTrZWrDAf9zUhDzy9X6ApHLCu3iAhLjN"
local:2>get laravel_cache:nOz7DwByMTrZWrDAf9zUhDzy9X6ApHLCu3iAhLjN
"s:239:"a:6:{s:6:"_token";s:40:"XMKXtYmhu2gIwGDhCLUHDBJkCzFUBjKnsqPU0Vcs";s:2:"mm";s:2:"aa";s:2:"kk";s:2:"bb";s:2:"cc";s:2:"ff";s:9:"_previous";a:1:{s:3:"url";s:27:"http://127.0.0.1:8091/api/t";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}";"
可以看出该key为laravel_cache+session_id
的格式,而且3个session的key value都存储在同一个key下,也就是说每个session_id会存储一个新key,该session_id下的所有session都存储在该key下,而不是多个key存储。
redis实现session的共享
由于系统用户的逐渐增多,我们通过使用负载均衡用户的访问流量,这时就会出现一个问题:
当用户A登录时,流量分发到后台集群的A节点,登录成功后session信息存储在A节点本地,当用户A刷新请求时,流量分发到了后台的集群B节点,由于此时B节点没有存储用户A的登录信息,所以又会提示用户A登录,这种现象对于用户体验是相当不好的,有以下俩种方式解决:
- 负载均衡器开启
会话保持
,负载均衡器将会将同一ip地址请求到同一个后台处理器。 - 使用redis做为session的驱动,后台所有服务器节点调用相同的redis。由于
同一域名下的网站的cookie都是一样的
,虽然调用不同的服务器节点,但是可以拿到相同的sesssion_id,也就可以避免上面出现的这种情况了。
session优点
- session保存在服务端,安全性相对于cookie更好
session缺点
- session同样时依附客户端的cookie,所以cookie的缺点同样是session的缺点。
session的使用方法
- 增加session
$_SESSION['userId']=12
删除session
unset() 函数用于释放指定的 session 变量:
unset($_SESSION['views']);
session_destroy() 函数彻底销毁 session:
session_destroy();
- 修改session
$_SESSION['userId']=12
- 查询session
//查询所有的session
dd($_SESSION);
//查看单独的session
dd($_SESSION['userId'])
测试
- chrome禁用cookie后,session能否使用
1.写一个api
public function index(Request $request)
{
session_start();
$_SESSION['yy']=33333;
echo $_SESSION['yy']."\n";
echo session_id();
}
-
访问该api,可以看到可以访问session yy。
3.我们上面不是说的不能访问session了吗?经发现,不关闭浏览器的情况下,刷新页面后session_id是一直在变化的,也就是说,不能保持同一会话了。也就是说上次设置的session,在下次刷新页面后,session将不能访问。
- 为了验证上面的说法,重写api
public function index(Request $request)
{
session_start();
//$_SESSION['yy']=33333;
echo $_SESSION['yy']."\n";
echo session_id();
}
5。 访问
在没禁用cookie的情况下。这里不关闭浏览器刷新页面的话是可以访问session yy的,因为session_id不会变,属于同一会话。
而此时我们刷新页面访问,应该session yy是不能访问的
和预想的一样
总结:把客户端的cookie禁用后,可以继续使用session,只是在不关闭浏览器的情况下不会保持同一会话了,也就是所有session都会消失。
Local Storage
localStorage 是 HTML5 标准中新加入的技术,它并不是什么划时代的新东西。早在 IE 6 时代,就有一个叫 userData 的东西用于本地存储,而当时考虑到浏览器兼容性,更通用的方案是使用 Flash。而如今,localStorage 被大多数浏览器所支持,如果你的网站需要支持 IE6+,那以 userData 作为你的 polyfill 的方案是种不错的选择。
Session Storage
sessionStorage 与 localStorage 的接口类似,但保存数据的生命周期与 localStorage 不同。做过后端开发的同学应该知道 Session 这个词的意思,直译过来是“会话”。而 sessionStorage 是一个前端的概念,它只是可以将一部分数据在当前会话中保存下来,刷新页面数据依旧存在。但当页面关闭后,sessionStorage 中的数据就会被清空。
我们后台的session是浏览器关闭后,session存储的消息不能共享,而Session Storage只要页面关闭后,session中的数据就会清空
cookie,Local Storage,Session Storage的对比
Local Storage,Session Storage两者的不同点在于:
1、生命周期
—— 数据可以存储多少时间
- localStorage: 存储的数据是永久性的,除非用户人为删除否则会一直存在。
- sessionStorage: 与存储数据的脚本所在的标签页的有效期是相同的。一旦窗口或者标签页被关闭,那么所有通过 sessionStorage 存储的数据也会被删除。
2、作用域
—— 谁拥有数据的访问权
- localStorage: 在同一个浏览器内,
同源文档
之间共享 localStorage 数据,可以互相读取、覆盖。 - sessionStorage: 与 localStorage 一样需要同一浏览器同源文档这一条件。不仅如此,sessionStorage 的作用域还被限定在了窗口中,也就是说,只有
同一浏览器
、同一窗口
的同源文档才能共享数据。