导语
我们在做项目的时候,经常把Cookie和Session挂在嘴边,可实际对于他们了解的也是很少,只是会使用,但这远远不够,熟练的掌握他们的特性才能把项目做的更好。下面我们就来认识一下他们吧!
### 先来了解一下Cache
Cache表示数据缓存,合理的设置cache,它可以帮助我们提高访问速度,减少请求(在缓存有效期内直接读取Cache文件),减少文件从服务器直接拉取文件(缓存过期后,请求服务器器检查文件是否被更改,如没有被更改则返回304然后读取Cache);
Cache的数据一般是服务器上不经常变动的数据,如图片、某些数据js、html、php等;如果是经常变动的数据一般是不被缓存的,没有意义;如果把一个经常变动的文件缓存起来的话,没有多大意义。
读取Cache的过程
首先检查文件设置的缓存是否过期:
- 如果过期了,则会重新发送请求到服务器,检查该文件是否有被更新,如果没有被更新,则服务器会返回304 Not Modified,表示服务器上该文件没有被更新,用户发起的对该文件请求则会直接从本地cache读取;如果服务上文件被更新了,则服务器会返回新的文件,此时http返回码为200 ok,更新缓存。
- 如果没有过期,则会直接读取本地cache文件,不再发起http请求;
在浏览器的控制台的Network,我们可以看到一些文件的Headers,我们来说说其中的一些头部设置的作用:
Responese Headers
access-control-allow-origin:*
cache-control:max-age=691200
content-length:0
date:Sun, 22 Apr 2018 03:25:41 GMT
etag:"5ad8603c-214cb"
expires:Fri, 27 Apr 2018 13:33:04 GMT
server:marco/2.0
status:304
via:T.3.H, M.ctn-fj-foc-007
x-request-id:30e1ceac71122f15ed9144c272406682
Request Headers
:authority:static.segmentfault.com
:method:GET
:path:/v-5ad86038/3rd/assets.js
:scheme:https
accept:*/*
accept-encoding:gzip, deflate, sdch, br
accept-language:zh-CN,zh;q=0.8
cache-control:max-age=0
if-modified-since:Thu, 19 Apr 2018 09:24:12 GMT
if-none-match:W/"5ad8603c-214cb"
origin:https://segmentfault.com
referer:https://segmentfault.com/user/settings?tab=notify
user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.5006.400 QQBrowser/9.7.13080.400
- expires
expires是HTTP/1.0控制网页缓存的字段,表示服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果;expires=当前服务器date+缓存有效时间;时间格式为GTM,是一个绝对值。
cache-control
用户控制http的缓存,max-age表示客户端可以接收生存期不大于指定时间(以秒为单位)的响应;max-age=0;表示每次请求该文件时,都需要请求服务器检查文件在上一次被缓存时有无修改过;max-age=10;表示10s内再次对该文件发起请求则不需要向服务器发起请求读取文件,直接读取本地cache文件;
在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存,主要取值为:
- public:所有内容都将被缓存(客户端和代理服务器都可缓存)
- private:所有内容只有客户端可以缓存,Cache-Control的默认取值
- no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
- no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
- max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效,是一个相对值
由于**Cache-Control的优先级比expires**,那么直接根据Cache-Control的值进行缓存,意思就是说在600秒内再次发起该请求,则会直接使用缓存结果,强制缓存生效。
***注:在无法确定客户端的时间是否与服务端的时间同步的情况下,Cache-Control相比于expires是更好的选择,所以同时存在时,只有Cache-Control生效。***
以上只是简单的了解一下Cache,更深入的了解浏览器的缓存机制,可以看看这篇文章–>彻底理解浏览器的缓存机制,讲得深入,看完会对你有很大的帮助。
Cookie
Cookie是客户端存储数据的一个一种选项。
当我们向服务器发送任意的HTTP请求的时候,服务器会返回一个带有Set-Cookie的HTTP响应头返回给浏览器,其中包含一些会话信息。这种响应头可能如下:
// Response Headers 响应头
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Sun, 22 Apr 2018 06:16:14 GMT
Content-Type: text/html
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: SID=t65ln3kllu7ujutldk4hcota05; path=/
Content-Encoding: gzip
这个响应头设置SID为名称,t65ln3kllu7ujutldk4hcota05为值的一个Cookie。
如果用户不是第一次访问,即:本地已经存在cookie,则在发送请求时会将cookie一并发给服务器,服务器收到请求之后会作出相应处理,返回对应的信息;这种请求头可能如下:
// request Headers 请求头
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8
Connection:keep-alive
Cookie: SID=t65ln3kllu7ujutldk4hcota05
Cookie的设置
设置方式为:
document.cookie="name=value;domain=域名;path=/;expires=过期时间;secure"
其中name和value是必须,其他为可选;name和value都需要经过URL编码–encodeURIComponent()
现在介绍一下Cookie的构成:
- name :一个唯一确定Cookie的名称,不区分大小写,获取Cookie是根据name来查找
- value:存储在Cookie中的字符串值
- domain:Cookie对于哪个域有效,比如domain=”aa.qq.com”,那么qq.com就不可以读取该Cookie,如果没有设置,会默认该请求来自当前域。
- path:对于指定域中的哪个路径。比如path=”/book/”,那么对于www.aa.qq.com/cc/的请求就不能发送Cookie
- expires:Cookie过期时间,这个值是GMT格式的日期
- secure:设置这个标志后,Cookie只有在SSL链接的时候才会发送给服务器,比如https://www.aa.qq.com可以,而http://www.aa.qq.com就不行
Cookie的缺点
Cookie在每个浏览器以及版本的数量都不同
- IE6一下版本每个域名最多20个
- IE7以上的版本每个域名最多50个
- FireFox每个域名最多50个
- Opera每个域名最多30个
- Safari和Chrome没有硬性规定,应该是有一个极限的
- 大小受限,一般是在4k左右,最好别超过4k
- 用户可以操作禁用cookie,使功能受限
- 安全性较低
- 有些状态不可能保存在客户端
- 每次访问都要传送cookie给服务器,浪费带宽。
- cookie数据有路径(path)的概念,可以限制cookie只属于某个路径下。
浏览器提供设置Cookie方法比较简陋,操作会比较麻烦,我们可以自己动手封装一个
class CookieUtil{
constructor(){
}
get(name){
var cookies=document.cookie.split(";");
var curCookie;
for(var i=0;i<cookies.length;i++){
curCookie=cookies[i].split("=");
if(decodeURIComponent(curCookie[0])===name){
return decodeURIComponent(curCookie[1])
}
}
return null;
}
set(name,value,expires,domain,path,secure){
if(!name&&!value){
return
}
var cookieStr=encodeURIComponent(name)+"="+encodeURIComponent(value);
if(expires && (expires instanceof Date)){
cookieStr+=";expires="+expires.toGMTString();
}
if(path){
cookieStr+=";path="+path
}
if(domain){
cookieStr+=";domain="+domain
}
if(secure){
cookieStr+=";secure"
}
document.cookie=cookieStr;
}
delete(name,domain,path,secure){
this.set(name,"",new Date(0),domain,path,secure)
}
}
Session
Session是保存在服务端的,通过类似与Hashtable的数据结构来保存,能支持任何类型的对象(session中可含有多个对象)
Session机制
当服务器收到请求需要创建session对象时,首先会检查客户端请求中是否包含sessionid。如果有sessionid,服务器将根据该id返回对应session对象。如果客户端请求中没有sessionid,服务器会创建新的session对象,并把sessionid在本次响应中返回给客户端。通常使用cookie方式存储sessionid到客户端,在交互中浏览器按照规则将sessionid发送给服务器。如果用户禁用cookie,则要使用URL重写,可以通过response.encodeURL(url)进行实现;API对encodeURL的约束为:当浏览器支持Cookie时,url不做任何处理;当浏览器不支持Cookie的时候,将会重写URL将SessionID拼接到访问地址后。
Session的优点
- 大小没有限制
session的安全性大于cookie,原因如下:
- sessionID存储在cookie中,若要攻破session首先要攻破cookie
- sessionID是要有人登录,或者启动session_start(php中的方法)才会有,所以攻破cookie也不一定能得到sessionID
- 第二次启动session_start后,前一次的sessionID就是失效了,session过期后,sessionID也随之失效。
- sessionID是加密的
Session的缺点
- Session保存的东西越多,就越占用服务器内存,对于用户在线人数较多的网站,服务器的内存压力会比较大。
- 依赖于cookie(sessionID保存在cookie),如果禁用cookie,则要使用URL重写,不安全
- 创建Session变量有很大的随意性,可随时调用,不需要开发者做精确地处理,所以,过度使用session变量将会导致代码不可读而且不好维护。
Storage
WebStorage目的是克服由cookie所带来的一些限制,当数据需要被严格控制在客户端时,不需要持续的将数据发回服务器。
Webstorage的两个主要目标:
- 提供一种在cookie之外存储会话数据的路径。
- 提供一种存储大量可以跨会话存在的数据的机制。
HTML5的WebStorage提供了两种API:localStorage(本地存储)和sessionStorage(会话存储)。
生命周期
- localStorage:localStorage的生命周期是永久的,关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。
- sessionStorage的生命周期是在仅在当前会话下有效。sessionStorage引入了一个“浏览器窗口”的概念,sessionStorage是在同源的窗口中始终存在的数据。只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。但是sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面,sessionStorage也是不一样的。
存储大小:
- localStorage和sessionStorage的存储数据大小一般都是:5MB
存储位置:
- localStorage和sessionStorage都保存在客户端,不与服务器进行交互通信。
存储内容类型:
- localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理
获取方式:
- localStorage:window.localStorage;;
- sessionStorage:window.sessionStorage;。
应用场景:
- localStoragese:常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据。
- sessionStorage:敏感账号一次性登录;
WebStorage的优点:
存储空间更大:
- cookie为4KB,而WebStorage是5MB;
节省网络流量:
- WebStorage不会传送到服务器,存储在本地的数据可以直接获取,也不会像cookie一样美词请求都会传送到服务器,所以减少了客户端和服务器端的交互,节省了网络流量;
- 对于那种只需要在用户浏览一组页面期间保存而关闭浏览器后就可以丢弃的数据,sessionStorage会非常方便;
快速显示:
- 有的数据存储在WebStorage上,再加上浏览器本身的缓存。获取数据时可以从本地获取会比从服务器端获取快得多,所以速度更快;
安全性:
- WebStorage不会随着HTTP Header发送到服务器端,所以安全性相对于cookie来说比较高一些,不会担心截获,但是仍然存在伪造问题;
WebStorage提供了一些方法,数据操作比cookie方便;
- setItem (key, value) —— 保存数据,以键值对的方式储存信息。
- getItem (key) —— 获取数据,将键值传入,即可获取到对应的value值。
- removeItem (key) —— 删除单个数据,根据键值移除对应的信息。
- clear () —— 删除所有的数据
- key (index) —— 获取某个索引的key