重新认识cookie、session和localStorage、sessionStorage

前言

本文将会系统的梳理一下cookie、session和localStorage、sessionStorage的发展史,概念,作用场景等,其中主要的两处作用场景:浏览器缓存机制和token、jwt、单点登录单独总结文章,有需求的小伙伴可以看一下;

一、cookie和session


1.1 发展史

在Web发展史中,浏览器和服务器之间的是通过HTTP协议交流的,但HTTP协议最重要的特点之一就是无状态
最开始Web基本就是文档的浏览,所以服务端无需知道是谁在请求,客户端每次请求都是一个新的HTTP协议;
随着交互式Web应用的兴起,例如购物商城网站,社区形式的网站…都是这些需要登录的网站,我们要知道哪些人买了哪些商品,哪些人往自己的购物车放了哪些商品…由于 HTTP 是无状态的协议,一旦客户端和服务器的数据交换完毕,就会断开连接,再次请求,会重新连接,这就说明服务器单从网络连接上是没有办法知道用户身份的。为了解决这个问题,就给每次新的用户请求时,发一个身份证,每次访问都要带上身份证,这样服务器就知道是谁来访问了,针对不同的用户做出不同的响应。

会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。

1.2 cookie是什么

HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能;
通俗解释:

  • cookie 是浏览器访问服务器后,服务器传给浏览器的一段数据,是浏览器提供的一种机制。
  • 浏览器需要保存这段数据,不得轻易删除。
  • 此后每次浏览器访问该服务器,都必须带上这段数据。

1.3 cookie的创建和删除

当前Cookie有两个版本,分别对应两种设置响应头:“Set-Cookie”和“Set-Cookie2”。在Servlet中并不支持Set-Cookie2,所以这里只说Set-Cookie(详见Set-Cookie MDN):Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]

属性属性介绍
Set-Cookie: <cookie-name>=<cookie-value>1.键值对,可以设置保存的Key/Value,这里NAME不能和其他属性项名字一样
2. name=value键值对,设置 Cookie 的名称及相对应的值,都必须是字符串类型,如果值为 Unicode 字符,需要为字符编码。如果值为二进制数据,则需要使用 BASE64 编码。
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>过期时间,在这个时间点后Cookie失效,形式为符合 HTTP-date 规范的时间戳
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>1. 在 cookie 失效之前需要经过的秒数。一位或多位非零(1-9)数字。假如二者 (指 Expires 和Max-Age) 均存在,那么 Max-Age 优先级更高。
2. cookie 失效的时间,单位秒。如果为整数,则该 cookie 在 maxAge 秒后失效。如果为负数,该 cookie 为临时 cookie ,关闭浏览器即失效,浏览器也不会以任何形式保存该 cookie 。如果为 0,表示删除该 cookie 。默认为 -1。
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>生成cookie域名,指定 cookie 可以送达的主机名。假如没有指定,那么默认值为当前文档访问地址中的主机部分(但是不包含子域名)。默认是当前域名。
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>cookie 在哪个路径(路由)下生效,指定一个 URL 路径,默认是 ‘/’。如果设置为 /abc,则只有 /abc 下的路由可以访问到该 cookie,如:/abc/read。
Set-Cookie: <cookie-name>=<cookie-value>; Secure加密设置,cookie只有在请求使用安全协议SSL或者HTTPS的时候才会被发送到服务器;默认为false。(注意:非安全站点(http:)已经不能再在 cookie 中设置 secure 指令了)
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly1. 设置了 HttpOnly 属性的 cookie 不能使用 JavaScript 经由 Document.cookie 属性、XMLHttpRequest 和 RequestAPIs 进行访问,以防范跨站脚本攻击(XSS)。
2. 如果给某个 cookie 设置了 httpOnly 属性,但还是能通过 Application 中手动修改 cookie,所以只是在一定程度上可以防止 XSS 攻击,不是绝对的安全.

详细解释一下Domain的应用,这里常用公司内部统一Auth中心登录
假设现在有两个域名:
域名A:a.test.f.com.cn
域名B:b.test.f.com.cn
显然,域名A和域名B都是f.com.cn的子域名

  • 如果我们在域名A中的cookie的domain设置为f.com.cn,那么f.com.cn及其子域名都可以获取这个cookie,即域名A和域名B都可以获取这个cookie。
  • 如果域名A和域名B同时设置cookie的doamin为f.com.cn,那么将出现覆盖的现象。
  • 如果域名A没有显式设置cookie的domain方法,那么domain就为a.b.f.com.cn,不一样的是,这时,域名A的子域名将无法获取这个cookie。
// 后端设置cookies
 if(found){
    // 设置cookie
   response.setHeader('Set-Cookie', `login_email=${email}`)
   response.statusCode = 200
   response.write('success')
 }
// node设置cookie
const Koa = require('koa')
const Router = require('koa-router')
const static = require('koa-static')
const app = new Koa();
const router = new Router();
app.use(static(__dirname,'/'))

router.get('/',async ctx=>{
	//观察cookie存在
    console.log('cookie:',ctx.header.cookie)
    //设置cookie
    ctx.set('Set-Cookie','cookie1=1234')
})

app.use(router.routes())
app.listen(1024,() => {
    console.log('1024已开启');
})
// 前端js操作cookie
// 目前document.cookie对cookie的操作很不友好,所以在项目中我们一般会引入第三方插件库来操作cookie
var dates=new Date();
dates.setDate(dates.getDate()+3); // 按天数设置
document.cookie=”user1=YY; expires=”+dates;

在这里插入图片描述
删除cookies
通过设置cookie的有效期在当前时间之前,就可以删除cookie。

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

1.4 cookie的特性

cookie分类

  1. 会话级别cookie: 所谓会话级别cookie,就是在浏览器关闭之后cookie就会失效。
  2. 持久级别cookie: 保存在硬盘的cookie,只要设置了过期时间就是硬盘级别cookie。

cookie的特点

  1. 域和路径:cookie 不可跨域,cookie可以跨越同域名下的多个网页,实现跨页面全局变量。
  2. 时间:Cookie 的默认有效期理论上在用户关闭页面后就失效,实际上在在20分钟左右,不同浏览器策略不同。但是后端可以强制设置有效期(如何设置见下文)。
  3. 空间:cookie存在客户端,只能存储4kb。
  4. 数量:一个浏览器针每个域最多存 20 个cookie,浏览器一般只允许存放 300 个cookie。
  5. 储存类型:cookie只能存储字符串。
  6. 无感知: cookie 可以借助 HTTP 头、浏览器的能力做到做到前端无感知传输数据。

cookie的缺点

  1. 不安全性——cookie很容易被用户篡改。( session 可以解决这个问题,防止用户篡改)
  2. 储存空间——cookie存储空间很小。(只有4kb左右)
  3. 数量有限——一个浏览器针每个域最多存 20 个cookie,浏览器一般只允许存放 300 个cookie。
  4. cookie可能被客户禁用。

1.5 cookie应用场景

cookie的主要应用场景是以下三方面:

  • 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
  • 个性化设置(如用户自定义设置、主题等)
  • 浏览器行为跟踪(如跟踪分析用户行为等)

例如:用户登录识别(实际会更谨慎)
用户 A 用浏览器访问了http://a.com,那么http://a.com 的服务器就会立刻给 A 返回一段数据「uid=1」(这就是 cookie)A把这段数据储存在本地。当 A 再次访问 http://a.com的其他页面时,就会附带上「uid=1」这段数据。这样服务端就知道 A 是谁了。

1.6 使用cookie需要注意的问题

  • 因为存储在客户端,容易被客户端篡改,使用前需要验证合法性
  • 不要存储敏感数据,比如用户密码,账户余额
  • 使用 httpOnly 在一定程度上提高安全性
  • 尽量减少 cookie 的体积,能存储的数据量不能超过 4kb
  • 设置正确的 domain 和 path,减少数据传输
  • cookie 无法跨域 (关于cookie跨域可以看一下withCredentials)
  • 一个浏览器针对一个网站最多存 20 个Cookie,浏览器一般只允许存放 300 个Cookie
  • 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

1.7 session是什么

session会话机制是一种服务器端机制,它是基于cookie来工作的,session 存储在服务器端,sessionId 会被存储到客户端的cookie 中;session的本质:就是存储在服务器上的一个哈希表。

// 之前的写法:直接将数据放到cookie里面:
// 一是会暴露用户的个人信息;二是用户可以直接通过浏览器修改cookie,极有可能获取到别人的用户信息,极不安全。
response.setHeader('Set-Cookie', `login_email=${email}`)
// 设置cookie的中存储的值为一个随机数,当后台获取到cookie时,就可以获取到该随机数并在sessions这个对象中查找key为这个随机数的value,即知道用户的用户名,明码,邮箱等 
let sessions = {}
let sessionId = Math.random() * 10000 // 设置sessionId 为一个随机数
sessions[sessionId] = {login_email:email} // 将email 存储在sessions这个对象中
response.setHeader('Set-Cookie', `sessionId = ${sessionId}`)  // cookie中存储的是 sessionId 这个随机数

在这里插入图片描述
session的一些特性:

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

1.8 session实现原理

在这里插入图片描述
session 认证流程:

  • 用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 session。
  • 请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器。
  • 浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名。
  • 当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。

1.9 使用session需要注意的问题

  • 将 session 存储在服务器里面,当用户同时在线量比较多时,这些 session 会占据较多的内存,需要在服务端定期的去清理过期的 session
  • 当网站采用集群部署的时候,会遇到多台 web 服务器之间如何做 session 共享的问题。因为 session 是由单个服务器创建的,但是处理用户请求的服务器不一定是那个创建 session 的服务器,那么该服务器就无法拿到之前已经放入到 session 中的登录凭证之类的信息了。
  • 当多个应用要共享 session 时,除了以上问题,还会遇到跨域问题,因为不同的应用可能部署的主机不一样,需要在各个应用做好 cookie 跨域的处理。
  • sessionId 是存储在 cookie 中的,假如浏览器禁止 cookie 或不支持 cookie 怎么办? (在下面有具体方法)
  • 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

1.10 session与cookie总结

相同点:session和cookie都是为了让http协议有状态而存在。

session是基于cookie的,如果浏览器中禁止了 Cookie,如何能实现session保障整个机制的正常运转。

  1. 后端用JSON的方式传回sessionID,之后储存在localStorage中;每次请求中都携带一个 sessionID 的参数,也可以 post 的方式提交,也可以在请求的地址后面拼接 xxx?SessionID=123456…。
  2. Token 机制。Token 机制多用于 App 客户端和服务器交互的模式,也可以用于 Web 端做用户状态管理。当用户第一次登录后,服务器根据提交的用户信息生成一个 Token,响应时将 Token 返回给客户端,以后客户端只需在Header头带上这个 Token 前来请求数据即可,无需再次登录验证。
  3. 通过隐藏表单传递SessionID。

session和cookie的区别

  1. 安全性: session 比 cookie 安全,session 是存储在服务器端的,cookie 是存储在客户端的。
  2. 存取值的类型不同:cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,session 可以存任意数据类型。
  3. 有效期不同: cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,session 一般失效时间较短,客户端关闭(默认情况下)或者 session 超时都会失效。
  4. 存储大小不同: 单个 cookie 保存的数据不能超过 4K,session 可存储数据远高于 cookie,但是当访问量过多,会占用过多的服务器资源,session最大的缺点就是占内存

考虑分布式 session 问题

在互联网公司为了可以支撑更大的流量,后端往往需要多台服务器共同来支撑前端用户请求,那如果用户在 A 服务器登录了,第二次请求跑到服务 B 就会出现登录失效问题。针对以上问题分布式 session 一般会有以下几种解决方案:

  • Nginx ip_hash 策略,服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 session,第二次分发到服务器 B 的现象。
  • session 复制,任何一个服务器上的 session 发生改变(增删改),该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点。
  • 共享 session,服务端无状态话,将用户的 session 等信息使用缓存中间件(如redis)来统一管理,保障分发到每一个服务器的响应结果都一致。
    在这里插入图片描述

二、localStorage和sessionStorage


1.1 发展史

WebStorage目的是克服由cookie所带来的一些限制,当数据需要被严格控制在客户端时,不需要持续的将数据发回服务器。Webstorage的两个主要目标:

  1. 提供一种在cookie之外存储会话数据的路径。
  2. 提供一种存储大量可以跨会话存在的数据的机制。

1.2 localStorage和sessionStorage是什么

HTML5的WebStorage提供了两种API,它们是window对象下的一个方法:

  1. window.localStorage(本地存储)
  2. window.sessionStorage(会话存储)

localStorage 的实质是一个存储在计算机本地的哈希表

1.3 localStorage和sessionStorage有什么特性

localStorage

  • localStorage 与 HTTP 无关
  • localStorage保存在客户端,不与服务器进行交互通信,HTTP 不会带上 localStorage 的值
  • 只有相同域名的页面才能互相读取 localStorage(遵循同源策略)
  • 每个域名 localStorage 最大存储量为 5Mb 左右(每个浏览器不一样)
  • localStorage 理论上永久有效,除非用户清理缓存,无法设置过期时间
  • 应用场景localStorage:常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据。

sessionStorage

  • sessionStorage 与 HTTP 无关
  • sessionStorage保存在客户端,不与服务器进行交互通信,HTTP 不会带上 sessionStorage 的值
  • 只有相同域名的页面才能互相读取 sessionStorage(遵循同源策略),但是sessionStorage 的作用域还被限定在了窗口中,也就是说,只有同一浏览器、同一窗口的同源文档才能共享数据。

    例如你在浏览器中打开了两个相同地址的页面A、B,虽然这两个页面的源完全相同,但是他们还是不能共享数据,因为他们是不同窗口中的。但是如果是一个窗口中,有两个同源的iframe元素的话,这两个iframe的 sessionStorage 是可以互通的。

  • 每个域名 sessionStorage 最大存储量为 5Mb 左右(每个浏览器不一样)
  • sessionStorage 在用户关闭页面后(即 session 结束后或者说会话结束后)就失效,而且没办法控制;
  • 应用场景sessionStorage:敏感账号一次性登录;

1.4 localStorage和sessionStorage怎么使用

localStorage和sessionStorage常用API

  • setItem (key, value) —— 保存数据,以键值对的方式储存信息。

    localStorage.setItem('myCat', 'Tom')
    

    访问当前域名下的本地 storage 对象,并增加了一个数据项通过使用storage.setItem() 作为 storage 接口的方法,接受一个键名和值作为参数,将会把键名添加到存储中,如果键名已存在,则更新其对应的值。

  • getItem (key) —— 获取数据,将键值传入,即可获取到对应的value值。

    let cat = localStorage.getItem('myCat')
    
  • removeItem (key) —— 删除单个数据,根据键值移除对应的信息。

    localStorage.removeItem('myCat')
    
  • clear () —— 删除所有的数据

    localStorage.clear()
    
  • key (index) —— 获取某个索引的key

需要注意的是:localStorage 只能存 string,所以如果想存Object,就需要用JSON来存,举个例子:localStorage.setItem('jsonObj',JSON.stringify({name:'obj'})),然后如果想要解析这个 JSON 将其转换成对象可以使用 JSON.parse()

localStorage的常见用处

  • 首先我们需要知道JS机制中的变量有这样的问题:变量只在当前的会话期内有效。即只要刷新页面,之前存储的变量就被回收了。那么我们如何让之前所存储的变量在刷新页面之后还存在呢,所以就有了localStorage 来解决这个需求。
  • 通过使用 localStorage 完成了变量的持久化存储,因为localStorage实际上是存储在本地计算机中的,不会因为页面刷新就导致变量被回收。
let already = localStorage.getItem('isPrompt')
if(!already){
  alert('我们的页面改版啦')
  localStorage.setItem('isPrompt', true)
}esle{
   // 已经提示了就什么也不做
}

三、关于一些常见的问题

  • cookie 和 session 有什么关系?
    一般来说 session 是基于 cookie 实现的。cookie是存在客户端本地的,而session是保存在服务器上的。
  • cookie 和 localStorage 的区别是什么?
    cookie 每次请求会被带给服务器,而 localStorage不会;
    cookie的最大储存量一般只有4k,而localStorage 一般有5Mb ;
    cookie的有效期一般在用户关闭页面后就失效,而localStorage理论上永久有效。
  • cookie 和 localStorage 几乎没有关系,为什么要放在一起比较?
    这是由历史原因的:localStorage 是新API,在它出现以前,之前的前端如何实现跨页面的数据持久化存储呢?只能通过cookie ,要知道cookie 和 localStorage 都是存放在计算机本地,所以当时很多程序员都把数据放在cookie里,但是有个问题,你所有存在 cookie里面的东西,每次请求都会带到服务器里面去,如果cookie里面放的东西太多,那么每次请求就要花费更多的时间。所以要达到跨页面的数据持久化存储,最优解就是使用 localStorage。
  • 前端永远不要读或者写cookie(测试环境切换用户是可以的),读写cookie一系列的操作是后端需要完成的工作。(这里的前后端指的是代码上的分离而不是人员上的分离)

四、结束

以上就是梳理的cookie、session和localStorage、sessionStorage的发展、概念、作用等一系列的基础知识,关于它们最重要的登录token、jwt、单点登录等近期会总结一篇文章;(作为一名前端已从入门快到入院了!)
你真的了解 Cookie 和 Session 吗
浏览器缓存控制详解

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值