Express教程05:Cookie

阅读更多系列文章请访问个人GitHub博客,示例代码请访问这里

Cookie介绍

Cookie存储在浏览器,在浏览器请求服务器时,其中的数据都会被发送到服务端,经常使用来作用户信息校验等。html

但因为Cookie存储在浏览器,容易受到篡改,安全性较差。前端

使用cookie-parser处理Cookie

处理Cookie,可使用中间件cookie-parsergit

读取Cookie

示例代码:/lesson05/server.jsgithub

使用cookie-parser中间件时,须要先经过server.use(cookieParser())解析cookie,以后就能够在req.cookies属性中读取到cookie的值。express

在浏览器打开http://localhost:8080/cookie,在控制台写入cookie{"userName":"lee"}api

// 使用cookie-parser中间件,解析Cookie
server.use(cookieParser())

server.get('/cookie', (req, res, next) => {
  // 读取cookieParser解析的Cookie
  console.log(req.cookies)

  res.send(`cookies: ${JSON.stringify(req.cookies)}`)
})
复制代码

在浏览器打开http://localhost:8080/cookie,服务端打印结果为:{"userName":"lee"}浏览器

设置Cookie

示例代码:/lesson05/server.js安全

设置Cookie能够用Express自带的方法res.cookiebash

方法的第一个参数为设置的属性名,第二个参数为属性值,第三个参数为配置项,例如:服务器

server.get('/cookie', (req, res, next) => {
  // express自带的设置Cookie方法
  res.cookie('userName', 'lee', {
    // 设置该Cookie只能够由服务端访问,即前端JavaScript没法访问document.cookie获取该值,但控制台仍是能够查看和修改
    httpOnly: true,
    // 只有经过HTTPS请求的Cookie才被使用,不然都认为是错误的Cookie
    // secure: true,
    // 设置保存Cookie的域名,浏览器查找Cookie时,子域名(如translate.google.com)能够访问主域名(google.com)下的Cookie,而主域名(google.com)不能够访问子域名(如translate.google.com)下的Cookie
    // 本地测试可直接设置为localhost
    domain: 'localhost',
    // 设置保存Cookie的路径,浏览器查找Cookie时,子路径(如/map)能够访问根路径('/')下设置的Cookie,而根路径('/')没法访问子路径(如/map)下设置的Cookie
    path: '/',
    // 经过expires设置Cookie过时时间为14天后
    // expires: new Date(new Date().getTime() + 14 * 86400000),
    // 经过maxAge设置Cookie过时时间为14天后
    maxAge: 14 * 86400000,
  })

  // 读取cookieParser解析的Cookie
  console.log(req.cookies)

  res.send(`cookies: ${JSON.stringify(req.cookies)}`)
})
复制代码

在浏览器的控制台中,能够看到设置的Cookie为{"userName":"lee"},有效期是14天。

Cookie的签名

示例代码:/lesson05/server.js

Cookie的签名便是使用一个存储在服务端的密钥对Cookie进行加密,Cookie中存储的数据是通过密钥加密的,所以客户端若是对Cookie进行修改,服务端校验就没法经过。

设置密钥

若须要给Cookie进行签名,首先须要给cookieParser的第一个参数传入一个字符串密钥:

// 解析Cookie
server.use(cookieParser(
  // 签名用密钥,须要保密,仅存储在服务端
  'NpLRTpy1vbBzEw2JcAxpf970kOk2RViDn5wKwrMv'
))
复制代码

签名Cookie

这样就能够开始设置签名Cookie了,只须要在res.cookie方法的配置参数中设置signed: true属性:

res.cookie('password', 'test123', {
  httpOnly: true,
  domain: 'localhost',
  path: '/',
  maxAge: 14 * 86400000,
  // 开启该Cookie的签名模式
  signed: true
})
复制代码

在浏览器打开http://localhost:8080/cookie,能够看到Cookie中被设置了password属性,其值为s%3Atest123.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg

若是用decodeURIComponent方法进行解码,结果为s:test123.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg

其意义以下:

  1. s表示该Cookie为签名Cookie
  2. test123表示该Cookie设置的值
  3. HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg表示对该值的签名,也就是说当服务端接收到该Cookie时,会使用服务端的密钥对test123进行签名,再与HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg进行对比,若是正确才可使用。

此时能够看到服务端打印结果为signedCookies: {"password":"test123"}

在客户端修改签名的Cookie

若是用户在客户端对签名的Cookie进行了修改,例如在浏览器控制台,将password改成s%3Atest456.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg

此时在服务端打印的结果为signedCookies: {"password":false},表示校验失败。

同时浏览器中的Cookie值被从新修改成了s%3Atest123.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg

除非用户在修改签名的Cookie的值时,将该值的签名一块儿修改,不然校验是没法经过的。

但因为签名是由服务端的密钥计算而成,所以这个值一般是安全的。

不过,由于对Cookie进行签名,会占用更多的Cookie存储空间,而Cookie在浏览器中最多只能存储4K,因此签名不可滥用,只用来保护重要的数据便可。

相关文章
相关标签/搜索