浏览器持久化存储与HTTP缓存

浏览器持久化存储与HTTP缓存

本文主要学习一些HTTP高级知识,例如Session、LocalStorage、Cache-Control、Expires、ETag

主要是涉及到浏览器持久化存储和HTTP缓存的一些技术

Cookie自身存在问题,用户能随意篡改Cookie获得其它用户的隐私信息,为了解决这个问题出现了基于Cookie来实现的Session。

一 Session

Session实质上就是一块内存,如果有需要可以存在硬盘上。

sessionId

使用Cookie的时候,服务器会先个用户一个响应头,来设置Cookie

response.setHeader('Set-Cookie', `sign_in_email=${email}`)
response.statusCode = 200

通过sessionId来改写响应头Set-Cookie设置Cookie

let seesions ={}
// 在服务器端准备一个hash来存储session
...
let sessionId = Math.random()*100000
sessions[sessionId] = {sign_in_email: email}
response.setHeader('Set-Cookie', `sessionId=${sessionId}`)
response.statusCode = 200

在用户登录时,浏览器可以查看到响应头

登陆setcookie.png

再次访问该域名下的页面时Cookie就可以利用sessionId来得到用户隐私信息

cookie.png

使用随机数来做sessionId,最终把这一串随机数暴露给用户。服务器通过Set-Cookie给用户一个sessionId ,每次用户访问访问服务器的时候,服务器通过对应的sessionId来读取sessions里的信息,就知道了用户的隐私信息了,安全是利用随机数保证的。

var sessions = {
  sessionId: {sign_in_email: email},
}

二 持久化存储

1.localStorage

localStorage是HTML5提供的API

window.localStorage 实质上是一个浏览器全局环境下的hash

存在c盘的一个文件里,大小一般为5m,不同浏览器大小不同

如何使用

存对象时用JSON来存储,否则会被转换为字符串[Object Object]

// 1.添加键,值
localStorage.setItem('jsonString', JSON.stringify({name:'obj'}))
// 2.获得值
localStorage.getItem('jsonString')
//3.清空localStorage
localStorage.clear()

和其他变量的区别

在JavaScript脚本里的变量,会在页面关闭和刷新时就没有了,下一次打开的时候又重新生成。

localStorage里的变量持久化存储可以再以后使用。

在有localstorage前所有的变量在页面刷新的时候全部销毁,没有办法保存下来,每次都是新的

最典型的应用记录是否提示过用户

<script>
  let already = localStorage.getItem('以提醒用户')
  if(!already) { //already = null
    alert('我们是船新版本啦~')
    localStorage.setItem('以提醒用户', true)
  }else{
    
  }
</script>

2. SessionStorage

localStorage特点基本相同;不同点为LocalStorage若不清除就一直有效,SessionStorage在用户关闭页面后(会话结束)就会失效。

三 总结

3.1 Cookie

  1. 服务器通过Set-Cookie头给客服端一串字符串
  2. 客户端每次访问相同域名的网页时,必须带上这短字符串
  3. 客户端要在一段时间内保存Cookie
  4. Cookie默认在用户关闭页面后就失效,后台代码可以设置Cookie的过期时间
  5. 大小大概在4kb左右

3.2 Session

  1. 将 SessionID(随机数)通过 Cookie 发给客户端
  2. 客户端访问服务器时,服务器读取 SessionID
  3. 通过 SessionID 我们可以得到对应用户的隐私信息,如 id、email
  4. 服务器有一块内存(哈希表)保存了所有 session

3.3 localStorage

  1. LocalStorage 跟 HTTP 无关,HTTP 不会带上 LocalStorage 的值
  2. 只有相同域名的页面才能互相读取 LocalStorage(没有同源那么严格)
  3. 每个域名 localStorage 最大存储量为 5Mb 左右(每个浏览器不一样)
  4. 常用场景:记录有没有提示过用户(没有用的信息,不能记录密码)
  5. LocalStorage 永久有效,除非用户清理

四 HTTP缓存

用于web性能优化,假如说我们要访问的的文件比较大,我们请求完之后,下载需要花很长时间,当我们刷新页面的时候,虽然文件没有任何更新,但是我们又从服务器端下载了一遍大文件,导致每次响应时间依然很长。我们可以利用HTTP缓存来进行性能优化。

4.1Cache-Control

如何设置缓存

通过max-age设置缓存有效时间

if (path === '/js/main.js'){
    let string = fs.readFileSync('./js/main.js', 'utf8')
    response.setHeader('Content-Type', 'application/javascript;charset=utf-8')
    response.setHeader('Cache-Control', 'max-age=30')
    response.write(string)
    response.end()
  }

以上在响应头里加上Cache-Contorl,表示浏览器在30s内刷新页面也不会发起对main.js的请求,在本地的内存硬盘里加载main.js,加快浏览器的加载速度。

Cache-Contorl让浏览器在一段时间内不访问服务器,而是从本地的内存和硬盘上拿到所需资源,连请求都没有,所以页面加载就十分快。

cache-control.png

注意

  1. 在首页不能设置Cache-Control,我们刷一些论坛性质的或者新闻性质的网站,注重时效性,一般会把爆炸性的、高质量的内容放到首页去,如果我们看了一会,想刷新看看新的更新的内容,而你设了缓存,看到的还是10分钟之前的首页。
  2. 缓存尽量设置可能长的时间 ,如果一个文件长期不变,把它设为从缓存里面获得,知乎设置了32596169秒的有效时间,1年的时间。

如何更新缓存

开发者在入口处URL进行改变,来重新请求更新,要升级就改变URL

需要更新设置查询参数 ?v=3 来重新加载 版本号

需要更新在入口处URL更新,就会重新去加载最新的文件版本了。

...
<script src="./js/main.js?V2"></script>
...

当你更新代码之后,理论上只需要在URL上添加查询参数?V2即可。

4.2Expires以前使用

如果有了cache-controlExpires会被忽略

Expires 响应头包含日期/时间, 即在此时候之后,响应过期。

无效的日期,比如 0, 代表着过去的日期,即该资源已经过期。

如果在Cache-Control响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires 头会被忽略。

response.serHeader('Expiers', 'GM时间')什么时间缓存过期重新请求。

使用Expires要将时间转化为格林威治时间

var d = new Date() //Sat Feb 10 2018 11:18:54 GMT+0800 (CST)
d.toGMTString() //"Sat, 10 Feb 2018 03:18:54 GMT"
if (path === '/js/main.js'){
    let string = fs.readFileSync('./js/main.js', 'utf8')
    response.setHeader('Content-Type', 'application/javascript;charset=utf-8')
    response.setHeader('Expires', 'Sat, 10 Feb 2018 03:18:54 GMT')
    response.write(string)
    response.end()
  }

Expires是基于用户电脑的本地时间,若用户本地时间有错,所有缓存就会有错。所以优先使用Cache-Control

4.3ETag

The ETag HTTP response header is an identifier for a specific version of a resource. It lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content has not changed. Additionally, etags help prevent simultaneous updates of a resource from overwriting each other ("mid-air collisions").

If the resource at a given URL changes, a new Etag value must be generated. A comparison of them can determine whether two representations of a resource are the same. Etags are therefore similar to fingerprints, and might also be used for tracking purposes by some servers. They might also be set to persist indefinitely by a tracking server.

  • ETag HTTP响应头是对特定资源版本的识别
  • 如果这个资源的URL改变了,一定会生成一个新的ETag值,一个检验会决定它们是否是同一资源。因此Etag有一点像资源的指纹。

md5一个摘要算法,用于检验文件是否相同,给文件一个版本号。

MD5引入

//terminal
npm install md5
...
//在server.js引入
var md5 = require('md5');
...
// terminal
MD5 (mian.js) = 2bb84jdhfrh294r492348frwa9322

如何设置ETag缓存未更改的资源

if (path === '/js/main.js'){
    let string = fs.readFileSync('./js/main.js', 'utf8')
    response.setHeader('Content-Type', 'application/javascript;charset=utf-8')
    let flieMd5 = md5(string)
    response.setHeader('ETag', flieMd5)
    //response.setHeader('Expires', 'Sat, 10 Feb 2018 03:18:54 GMT')
    response.write(string)
    response.end()
  }

浏览器响应头如下

ETag响应头.png

再次刷新可以看到客服端发送的请求里会出现一个新的请求头If-None-Macth

ETag再次请求.png

服务器将客服端的ETag(If-None-Macth的值)与其当前版本的ETag进行比较,如果两个值匹配,服务返回不带响应第四部分的响应,也就是没有响应体。就是未修改的304 Not Modified状态

可以得知具体的实现如下

if (path === '/js/main.js'){
    let string = fs.readFileSync('./js/main.js', 'utf8')
    response.setHeader('Content-Type', 'application/javascript;charset=utf-8')
    let flieMd5 = md5(string)
    response.setHeader('ETag', flieMd5)
    if(request.headers['if-none-match'] !== flieMd5) {
      //有响应体,加载改变的资源
      response.write(string)
    }else{
      //没有响应体
      response.statusCode = 304
    }
    response.end()
  }

304 Not Modified

HTTP 304 说明无需再次传输请求的内容,也就是说可以使用缓存的内容。这通常是在一些安全的方法(safe),例如GETHEAD 或在请求中附带了头部信息: If-None-MatchIf-Modified-Since

304表示依然会有请求与响应,但是不会有响应的第四部分响应体。而是直接从本地的内存硬盘中获得。

五 常见题目

1.Cookie 和 Session 的区别

  1. Cookie 保存在客户端,每次都随请求发送给 Server

  2. Session 保存在 Server 的内存里,其 Session ID 是通过 Cookie 发送给客户端的

2.Cookie 和 LocalStorage 的区别

  1. window.LocalStorage实质上全局对象里的一个hash表,由HTML5提供的一个API,用于持久化存储;Cookie的大小一般在4k左右,LocalStorage的大小一般在5m左右不同浏览器大小不同
  2. Cookie属于HTTP内容,HTTP不会带上LocalStorage

3.LocalStorage 和 SessionStorage 的区别

LocalStorage若不清除就一直有效,SessionStorage在用户关闭页面后(会话结束)就会失效

4.Cookie 如何设置过期时间?如何删除 Cookie?

  1. 持久性Cookie:和关闭浏览器变失效的会话期Cookie不同,持久性Cookie可以指定一个特定时间(Expires)或有效期(Max-Age)
    Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

  2. 设置cookie过期时间小于当前时间,那么就会删除该cookie
    Set-Cookie: reg_fb_gate=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT

    function deleteCookie(name) {
      document.cookie = name + '=;  expires=Thu, 01 Jan 1970 00:00:01 GMT;'
    }
    

    在浏览器中删除存储的Cookie

5. Cache-Control: max-age=1000 缓存 与 ETag 的「缓存」有什么区别?

  1. Cache-Control: max-age =1000 是在这1000s内缓存有效,通过相同URL请求服务器时,浏览器在1000s不会发送HTTP请求访问服务器,而是从本地的内存和硬盘上拿到请求的资源。
  2. ETag:是通过校验两次请求资源的md5值是否改变来判断是否需要重新加载资源,是一定会发起HTTP请求且有响应,如果md5值相同,有请求有响应状态码304,但不会有响应的第四部分响应体;如果md5值不同,就会重新加载新的响应体。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容