美文网首页
Cookie、Session、LocalStorage、Cach

Cookie、Session、LocalStorage、Cach

作者: squall1744 | 来源:发表于2018-04-25 15:00 被阅读0次

    Cookie


    定义

    Cookie(复数形态Cookies),中文名称为“小型文本文件”或“小甜饼[1],指某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。由网景公司的前雇员卢·蒙特利在1993年3月发明[2]。最初定义于RFC 2109。目前使用最广泛的 Cookie标准却不是RFC中定义的任何一个,而是在网景公司制定的标准上进行扩展后的产物。

    分类

    Cookie总是保存在客户端中,按在客户端中的存储位置,可分为内存Cookie和硬盘Cookie。

    内存Cookie由浏览器维护,保存在内存中,浏览器关闭后就消失,硬盘Cookie保存在硬盘里,有一个过期时间,除非用户手工清理或到了过期时间,硬盘Cookie不会被删除,其存在时间是长期的。

    用途

    因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。

    比如购物网站, 由于http是无状态的, 所以如果不采用其他手段. 服务器根本不知道用户到底买了什么, 购物车里到底保存了什么,

    在刚才的购物场景中,当用户选购了第一项商品,服务器在向用户发送网页的同时,还发送了一段Cookie,记录着那项商品的信息。当用户访问另一个页面,浏览器会把Cookie发送给服务器,于是服务器知道他之前选购了什么。用户继续选购饮料,服务器就在原来那段Cookie里追加新的商品信息。结帐时,服务器读取发送来的Cookie就行了。

    特点

    1. 服务器通过 Set-Cookie 响应头设置 Cookie
    2. 浏览器得到 Cookie 之后, 每次请求都要带上 Cookie
    3. 服务器读取 Cookie 就知道登陆用户的信息
    4. Cookie 可以在开发者工具的 application 中修改
    5. Cookie 有效期默认20分钟左右
    6. 后端可以强制设置有效期

    过程图

    我们以登陆界面为例

    登陆

    session


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

    localStorage


    html5提供的一个API, 在浏览器建立一个哈希表用来存储内容, 只接受字符串

    使用

    localStorage干什么用?
    我们都知道, 假设我们在js里面声明了一个变量, 并给变量赋值, 当我们关闭或者刷新页面后, 之前声明的变量就销毁了, 没有办法永久保存, 当我们想要在关闭或刷新页面后, 持久化保留某个变量和它的值的时候, 就可以利用localStorage来保存它。


    localStorage

    假设我们有以下场景

    1. 第一次登陆网页提示网站改版
    2. 之后再登陆不提示

    我们就可以用 localStorage 实现

    let already = localStorage.getItem('alreadyAlert')
    if(!already) {
      alert('你好, 我们网站改版了, 有了这些新功能.....')
      localStorage.setItem('alreadyAlert', true)
    }
    

    特点

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

    SessionStorage

    1、2、3、4同上

    1. SessionStorage 在用户关闭页面后就失效
    2. 用法也同localStorage

    Cache-Control(缓存控制)


    缓存

    缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当 web 缓存发现请求的资源已经在本地存储,它就会拦截请求,返回保存的资源,而不会去源服务器重新下载。

    缓存可以缓解服务器端压力,提升性能(获取资源的耗时更短了)。对于网站来说,缓存是达到高性能的重要手段之一。缓存需要合理配置,因为并不是所有资源都是永久不变的:重要的是对一个资源的缓存应截止到其下一次发生改变(即不能缓存过期的资源)。

    缓存种类

    缓存的种类有很多,其大致可归为两类:私有缓存共享缓存
    共享缓存存储的响应能够被多个用户使用。私有缓存只能用于单独用户。
    我们主要介绍浏览器与代理缓存
    [站外图片上传中...(image-612554-1524639617439)]


    (私有)浏览器缓存

    私有缓存只能用于单独用户。你可能已经见过浏览器设置中的“缓存”选项。浏览器缓存拥有用户通过 HTTP 下载的所有文档。这些缓存为浏览过的文档提供向后/向前导航,保存网页,查看源码等功能,可以避免再次向服务器发起多余的请求。它同样可以提供缓存内容的离线浏览。

    (共享)代理缓存

    共享缓存可以被多个用户使用。例如,ISP 或你所在的公司可能会架设一个 web 代理来作为本地网络基础的一部分提供给用户。这样热门的资源就会被重复使用,减少网络拥堵与延迟。

    缓存控制

    Cache-control 头

    HTTP/1.1定义的 Cache-Control 头用来区分对缓存机制的支持情况, 请求头和响应头都支持这个属性。通过它提供的不同的值来定义缓存策略。

    禁止进行缓存

    缓存中不得存储任何关于客户端请求和服务端响应的内容。每次由客户端发起的请求都会下载完整的响应内容。

    Cache-Control: no-store
    Cache-Control: no-cache, no-store, must-revalidate
    

    强制确认缓存

    如下头部定义,此方式下,每次有请求发出时,缓存会将此请求发到服务器(该请求应该会带有与本地缓存相关的验证字段),服务器端会验证请求中所描述的缓存是否过期,若未过期(实际就是返回304),则缓存才使用本地缓存副本。

    Cache-Control: no-cache
    

    私有缓存和公共缓存

    "public" 指令表示该响应可以被任何中间人(比如中间代理、CDN等)缓存。若指定了"public",则一些通常不被中间人缓存的页面(因为默认是private)(比如 带有HTTP验证信息(帐号密码)的页面 或 某些特定影响状态码的页面),将会被其缓存。

    而 "private" 则表示该响应是专用于某单个用户的,中间人不能缓存此响应,该响应只能应用于浏览器私有缓存中。

    Cache-Control: private
    Cache-Control: public
    

    缓存过期机制

    过期机制中,最重要的指令是 "max-age=<seconds>",表示资源能够被缓存(保持新鲜)的最大时间。相对Expires而言,max-age是距离请求发起的时间的秒数。针对应用中那些不会改变的文件,通常可以手动设置一定的时长以保证缓存有效,例如图片、css、js等静态资源。

    Cache-Control: max-age=31536000
    

    缓存验证确认

    当使用了 "must-revalidate" 指令,那就意味着缓存在考虑使用一个陈旧的资源时,必须先验证它的状态,已过期的缓存将不被使用。详情看下文关于缓存校验的内容。

    Cache-Control: must-revalidate
    

    新鲜度

    理论上来讲,当一个资源被缓存存储后,该资源应该可以被永久存储在缓存中。由于缓存只有有限的空间用于存储资源副本,所以缓存会定期地将一些副本删除,这个过程叫做缓存驱逐。另一方面,当服务器上面的资源进行了更新,那么缓存中的对应资源也应该被更新,由于HTTP是C/S模式的协议,服务器更新一个资源时,不可能直接通知客户端及其缓存,所以双方必须为该资源约定一个过期时间,在该过期时间之前,该资源(缓存副本)就是新鲜的,当过了过期时间后,该资源(缓存副本)则变为陈旧的驱逐算法用于将陈旧的资源(缓存副本)替换为新鲜的,注意,一个陈旧的资源(缓存副本)是不会直接被清除或忽略的,当客户端发起一个请求时,缓存检索到已有一个对应的陈旧资源(缓存副本),则缓存会先将此请求附加一个If-None-Match头,然后发给目标服务器,以此来检查该资源副本是否是依然还是算新鲜的,若服务器返回了 304 (Not Modified)(该响应不会有带有实体信息),则表示此资源副本是新鲜的,这样一来,可以节省一些带宽。若服务器通过 If-None-MatchIf-Modified-Since 判断后发现已过期,那么会带有该资源的实体内容返回。

    下面是上述缓存处理过程的一个图示:

    [站外图片上传中...(image-ea0fc1-1524639617440)]

    对于含有特定头信息的请求,会去计算缓存寿命。比如Cache-control: max-age=N的请求头,相应的缓存的寿命就是N。通常情况下,对于不含这个属性的请求则会去查看是否包含Expires属性,通过比较Expires的值和头里面Date属性的值来判断是否缓存还有效。如果max-age和expires属性都没有,找找头里的Last-Modified信息。如果有,缓存的寿命就等于头里面Date的值减去Last-Modified的值除以10(注:根据rfc2626其实也就是乘以10%)。

    缓存失效时间计算公式如下:

    expirationTime = responseTime + freshnessLifetime - currentAge
    

    上式中,responseTime 表示浏览器接收到此响应的那个时间点。

    缓存更新

    通常我们对于css文件和js文件的max-age都设置1年以上, 但是如果这期间文件更新了怎么办呢?

    只有url相同才会调用缓存, 所以当有文件更新时候, 对文件名加入随机数或者MD5值使文件路由地址不一样就可以了, 比如我们刚开始的文件

    <link rel="stylesheet"  href="/style.css">
    

    若文件更新了, 我们让文件名变成

    <link rel="stylesheet"  href="/style125445.css">
    

    这样引用文件的路由就变了, 这样就不会使用之前的缓存了

    下面的截图是百度的请求, css请求和js请求后面的那些不规则数字就是利用我们这种方法实现缓存更新的


    缓存更新

    Expires(不常用)

    在Cache-Control出来之前我们用Expires, 现在用的不多了, 这里就大概提一下, 比如在node中, 我们跟设置其他响应头一样, 在响应头中设置Expire时间, 到了那个时间缓存就会过期, 这个时间需要用GMT时间, 但是这有个缺点, 这个时间是根据机器的本地时间来判断的

    response.setHeader('Expires', 'Sun, 04 Feb 2018 14:3:05 GMT')
    

    Etag

    MD5
    信息摘要算法, 用于校验文件内容是否相同, 相同内容的文件MD5值相等, 内容差异越小, MD5值差异越大。
    通常我们在下载电影或者安装包等文件的时候经常会用到MD5校验, 用来校验我们下载的文件是不是跟目标文件一样。
    所以, 对于js文件或者css文件, 我们同样可以用MD5来判断文件是否相同, 假设我们在nodejs中已经引用了MD5包, 并算出了js文件的MD5值, 我们设置Etag并赋值为js文件的MD5值

    response.setHeader('ETag',  fileMD5)
    

    当我们在响应头中设置ETag后, 在下次请求过来时, 请求头就会带有一个if-none-match, 它的值就是上次响应头中的ETag值, 这样我们就可以在后端检验这个值, 如果这个值跟这次响应中的ETag值不相等, 就更新文件

    response.setHeader('ETag', fileMD5)
    if(request.headers['if-none-match'] === fileMD5) {
      response.statusCode = 304
      //不用返回响应体
    }else {
      // 返回新版js文件
      response.write(newJsFile)
      response.end()
    }
    

    相关文章

      网友评论

          本文标题:Cookie、Session、LocalStorage、Cach

          本文链接:https://www.haomeiwen.com/subject/mmrakftx.html