Cookie 与 session 的介绍和设置

Cookie 简介

当我们打开一个网站,点击地址栏旁边的小锁图标,可以查看当前网站正在使用的 Cookie,它们的类型都是“小型文本文件”:

image.png

根据存储位置的不同,可以将 Cookie 分为内存 Cookie(或称为 session cookie) —— 默认情况下,没有设置 Cookie 的到期时间,则在浏览会话结束时,也就是浏览器被关闭时就会被删除:

image.png

硬盘 Cookie —— 超过设置的到期时间或用户手动清理时才会被删除:

image.png

对于浏览器而言,在同一域名下,多个端口的 Cookie 是共享的,所以只有关闭浏览器而非当前标签页时,内存 Cookie 才会消失。另外,当网站发生请求时,Cookie 会随着请求头提交。这两点特性,与同样可以用于在客户端存储数据的 localstorage 和 sessionstorage 不同。

设置 Cookie

这些 Cookie 虽然是存储在客户端的,但既可以通过前端设置,也可以由后端设置。

前端

如下是通过原生代码设置 Cookie 的一个简单演示,在实际项目中,则可以使用 js-cookie 这个库来进行些 Cookie 操作:

<!-- 代码片段一 -->
<body>
  <button id="add">添加</button>
  <button id="remove">删除</button>
  <script>
    const addBtn = document.querySelector('#add')
    addBtn.onclick = () => {
      document.cookie = 'msg1=hello'
      document.cookie = 'msg2=juejin;max-age=60'
    }

    const removeBtn = document.querySelector('#remove')
    removeBtn.onclick = () => {
      document.cookie = 'msg1=hello;max-age=0'
      document.cookie = 'msg2=juejin;max-age=0'
    }
  </script>
</body>
复制代码

像代码片段一中第 8 行那样直接通过给 document.cookie 赋 k-v 值,即可添加 Cookie msg1,默认为内存 Cookie。如果像第 9 行那样通过 max-age 指定了过期时间(单位为秒),那么 msg2 就是一个硬盘 Cookie。

如果想手动删除 Cookie,可以如第 14、15 行代码那样,设置 max-age0。 点击“添加”按钮后,通过开发者工具查看 Cookie 结果如下:

image.png

可以看到,上图中显示 Cookie 还有两个属性 Domain 和 Path,用以表明哪些主机(Domain)或路径(Path)可以访问 Cookie。

默认情况下, Domain 的值为当前的域名,可以通过类似 document.cookie = 'msg=hello;domain=.baidu.com' 来设置,以实现子域名(比如 map.baidu.com)对 Cookie 的跨域访问;Path 的值为根路径 /,可以通过诸如 document.cookie = 'msg=hello;path=/article' 来设置。

后端

在使用 koa 搭建的后端项目中,如果想给发送请求的客户端设置 Cookie,只需在中间件中,直接通过 ctx.cookies.set() 即可:

const koa = require('koa')
const app = new koa()
app.use((ctx, next) => {
  ctx.cookies.set('msg', 'hello', {
    maxAge: 10 * 1000 // 单位为微秒
  })
  ctx.body = '随便返回点什么'
})
复制代码

如上,便会在接收到请求时,向客户端设置名称为 msg,值为 hello,过期时间为 10 s 的内存 Cookie。如果想获取请求携带的 Cookie,则可以通过 ctx.cookies.get() 获取:

app.use((ctx, next) => {
  const value = ctx.cookies.get('msg')
  console.log(value) // hello
  ctx.body = '随便返回点什么'
})
复制代码

session

在早期的项目中,Cookie 的设置主要是为了解决 http 请求是没有状态的这个问题,即服务器无法通过 http 请求来确定是谁发起的请求,所以人们通过设置 Cookie 来进行身份的验证。既然如此,像上文那样设置的 Cookie,值都是明文就不合适了。我们需要使用 session 来实现 session 认证,其实大体上就是给 Cookie 做个加密处理。在 koa 项目中可以安装 koa-session 来生成 session:

npm i koa-session
复制代码

在项目中导入,得到的 session 是一个函数,需要执行生成 session 并传入 app.use(),执行 session() 时需要传入一个配置对象和 app 对象,配置对象中 key 用于指定设置的 Cookie 的 key,一般取名为 sessionid

// 代码片段二
const session = require('koa-session')
app.use(
  session(
    {
      key: 'sessionid',
      signed: false
    },
    app
  )
)
复制代码

之后便可通过 ctx.session.xxx 来设置 sessionid 的值了:

app.use((ctx, next) => {
  ctx.session.msg = 'hello'
  ctx.body = '随便返回点什么'
})
复制代码

当浏览器发送了请求后,可以看到 Cookie 中新增了一条名称为 sessionid 记录,并且值是经过了加密处理的:

image.png

可以通过 ctx.session.xxx 获取 sessionid 的值:

app.use((ctx, next) => {
  const value = ctx.session.msg
  console.log(value) // hello
  ctx.body = '随便返回点什么'
})
复制代码

如果代码片段二中,将 session() 的配置里的 signed: false 删除,或是改为默认值 true,可以对 session 做进一步的加密处理,但是需要给 app.keys 设值,进行“加盐”操作:

app.keys = ['aa', 'bb', 'cc']
app.use(
  session(
    {
      key: 'sessionid'
    },
    app
  )
)
复制代码

现在,浏览器发送请求后,可以看到 2 条 Cookie 记录:

image.png

在获取 sessionid 时,我们虽然不需要添加额外的代码,但 koa-session 内部会去同时验证 sessionid.sigsessionid 的值。

session() 的配置项还可以传入其它的属性,比如设置 Cookie 的过期时间为 1 分钟:maxAge: 60 * 1000,具体可参见其 github 仓库

感谢.gif 点赞.png

本文正在参加「金石计划」

猜你喜欢

转载自juejin.im/post/7219557974846980151