Cookie存储在浏览器,在浏览器请求服务器时,其中的数据都会被发送到服务端,经常使用来作用户信息校验等。html
但因为Cookie存储在浏览器,容易受到篡改,安全性较差。前端
处理Cookie,可使用中间件cookie-parsergit
示例代码:/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"}
。浏览器
示例代码:/lesson05/server.js安全
设置Cookie能够用Express自带的方法res.cookie。bash
方法的第一个参数为设置的属性名,第二个参数为属性值,第三个参数为配置项,例如:服务器
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天。
示例代码:/lesson05/server.js
Cookie的签名便是使用一个存储在服务端的密钥对Cookie进行加密,Cookie中存储的数据是通过密钥加密的,所以客户端若是对Cookie进行修改,服务端校验就没法经过。
若须要给Cookie进行签名,首先须要给cookieParser的第一个参数传入一个字符串密钥:
// 解析Cookie
server.use(cookieParser(
// 签名用密钥,须要保密,仅存储在服务端
'NpLRTpy1vbBzEw2JcAxpf970kOk2RViDn5wKwrMv'
))
复制代码
这样就能够开始设置签名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
。
其意义以下:
s
表示该Cookie为签名Cookietest123
表示该Cookie设置的值HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg
表示对该值的签名,也就是说当服务端接收到该Cookie时,会使用服务端的密钥对test123
进行签名,再与HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg
进行对比,若是正确才可使用。此时能够看到服务端打印结果为signedCookies: {"password":"test123"}
。
若是用户在客户端对签名的Cookie进行了修改,例如在浏览器控制台,将password改成s%3Atest456.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg
。
此时在服务端打印的结果为signedCookies: {"password":false}
,表示校验失败。
同时浏览器中的Cookie值被从新修改成了s%3Atest123.HrZ44MCUeLXj0uZAzTpCXWduflOsmfBs5XsuK4eTMvg
。
除非用户在修改签名的Cookie的值时,将该值的签名一块儿修改,不然校验是没法经过的。
但因为签名是由服务端的密钥计算而成,所以这个值一般是安全的。
不过,由于对Cookie进行签名,会占用更多的Cookie存储空间,而Cookie在浏览器中最多只能存储4K,因此签名不可滥用,只用来保护重要的数据便可。