Cookie 和 Session

Cookie的特点:

  • Cookie 存储于客户端
  • Cookie 空间只有4k
  • Cookie 安全性非常差

可采取的措施:

  • 存储Cookie必须精打细算
  • 校验Cookie是否被篡改(签名)

设置 Cookie 很简单,只需要在请求中设置 res.cookie(key, value, options) 即可,其中options是可选的,

options 可以设置:

  • path 有效路径
  • maxAge 过期时间,单位是ms
  • signed 布尔值,是否签名
const express = require('express')
const app = express()
app.use('/', (req, res, next) => {
  res.cookie('user', 'xiaoyu', {path: '/aaa', maxAge: 30 * 24 * 3600 * 1000})
  res.send('Hello')
})
let server = app.listen(8088, () => {
  let host = server.address().address
  let port = server.address().port
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
})

读取 cookie,需要使用中间件 cookie-parser,是用于处理 cookie 的中间件。

const express = require('express')
const cookieParser = require('cookie-parser')
const app = express()
app.use(cookieParser())
app.use('/', (req, res, next) => {
  console.log(req.cookies)
})
let server = app.listen(8088, () => {
  let host = server.address().address
  let port = server.address().port
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
})

签名的目的: 防止篡改。

首先使用 app.use 加载 cookieParser,可以设置参数,即为签名秘钥。

使用 req.secret 设置Cookie签名 使用 req.signedCookies 获取签名的Cookie 使用 req.cookies 后去无签名的Cookie

const express = require('express')
const cookieParser = require('cookie-parser')
const app = express()
const secret = 'Asgfsdgdfsg'
app.use(cookieParser(secret))
app.use('/', (req, res, next) => {
  req.secret = secret
  res.cookie('name', 'xiaoyu', {signed: true})
  console.log('签名cookies: ', req.signedCookies)
  console.log('无签名cookies: ', req.cookies)
  res.send('Hello')
})
let server = app.listen(8088, () => {
  let host = server.address().address
  let port = server.address().port
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
})

使用 res.clearCookie() 即可删除指定名称的 Cookie

const express = require('express')
const cookieParser = require('cookie-parser')
const app = express()
const secret = 'Asgfsdgdfsg'
app.use(cookieParser(secret))
app.use('/', (req, res, next) => {
  req.secret = secret
  res.cookie('name', 'xiaoyu', {signed: true})
  res.cookie('age', '18', {signed: true})
  res.clearCookie('name')
  console.log('签名cookies: ', req.signedCookies)
  console.log('无签名cookies: ', req.cookies)
  res.send('Hello')
})
let server = app.listen(8088, () => {
  let host = server.address().address
  let port = server.address().port
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
})

加密 cookie,需要使用中间件 cookie-encrypter,是用于加密 cookie 的中间件。

Session

Session的特点:

  • Session 存储于服务器端
  • Session 无大小限制
  • Session 安全性高
  • 但是,Session是基于Cookie的,不能独立存在

Session 的使用

处理 Session,需要用到中间件 cookie-session

由于 Session 技术是基于 Cookie 的,不能独立存在,所以得先引入 cookie-parser

先看一个不安全的例子:

const express = require('express')
const cookieParser = require('cookie-parser')
const cookieSession = require('cookie-session')
const app = express()
app.use(cookieParser())
app.use(cookieSession())
app.use('/', (req, res, next) => {
  console.log(req.session)
  res.send('Hello')
})
let server = app.listen(8088, () => {
  let host = server.address().address
  let port = server.address().port
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
})

如果直接这样写,运行的时候会直接报错:

if (!keys && opts.signed) throw new Error('.keys required.')

这是由于直接使用 Session 可能会发生 Session 劫持,为了确保安全性,必须指定 keys (秘钥组)。

所以在使用 cookie-session 的时候,需要指定秘钥组(数组),理论上,秘钥数量越多安全。

const express = require('express')
const cookieParser = require('cookie-parser')
const cookieSession = require('cookie-session')
const app = express()
let secretArr = []
for (let i = 0; i < 100; i++) {
  secretArr.push('sig_' + Math.random())
}
app.use(cookieParser())
app.use(cookieSession({
  name: 'se',
  keys: secretArr,
  maxAge: 3600 * 1000
}))
app.use('/', (req, res, next) => {
  if (!req.session.count) {
    req.session.count = 1
  } else {
    req.session.count ++
  }
  console.log(req.session)
  res.send('Hello')
})
let server = app.listen(8088, () => {
  let host = server.address().address
  let port = server.address().port
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
})

从截图可以看出,Session 是基于 Cookie 的。

为了安全性考虑,我们还可以设置 Session 存在于 Cookie 中的名称和过期时间

app.use(cookieSession({
  name: 'se',
  keys: ['fdfdsfsdf','gfgdfgfgfg', 'hreyhretyfgf'],
  maxAge: 3600 * 1000
}))

删除Session

delete res.session

MIT Licensed | Copyright © 2018-present 滇ICP备16006294号

Design by Quanzaiyu | Power by VuePress