1.为什么说要利用签名防止cookie被恶意篡改
我们在浏览器输入用户名和密码发送post请求到后端服务器,后端服务器验证合法,返回响应,并Set-Cookie
为sessionid=***;username=water
,然后浏览器接受到响应发Set-Cookie
,于是将其存入内存或硬盘中;浏览器端再次发起请求,带上Cookie信息sessionid=***;username=water
,请求修改自己的头像信息,服务器根据sessionid
验证当前用户已登录,根据username
,查找数据库中的对应数据,修改头像信息,这是一个正常的cookie设置与利用cookie的过程。但是我们为什么说要防止Cookie被篡改呢?这是因为cookie是存储在客户端的,这时用户可以任意修改cookie值,比如如果当前用户知道username
的作用,修改username=fire
,根据username
,查找数据库中的对应数据,并修改了头像信息,这样就暴露出数据被恶意篡改的风险。其实就是服务端无法保证张三请求修改数据时到底是不是张三自己要求修改,也可能是李四是在恶意篡改张三的数据。这时我们就要给cookie增加签名,比如服务器接收到请求中的Cookie项username=fire||34sdklkas
,然后使用签名生成算法secret(fire)=666
,得到的签名666
和请求中数据的签名不一致,则证明数据被篡改,不予通过,所以cookie中不应该存储敏感数据,应该根据SessionID将敏感数据存储在后端,取数据时根据SessionID去后端服务器获取,对于一些重要的Cookie项,应该生成对应的签名来反之被恶意篡改。
- 签名就能够确保安全吗 我们只通过用户名这个cookie来判断登录的是哪一个用户,虽然增加了签名,而且秘钥我们也不知道,看起来很难伪造签名cookie,但是只要原始值相同的情况下,签名也是相同的,这汇总情况下就很容易伪造了,而且我们要确保秘钥的生成算法不被泄露。
- Express中cookie-parser中间件的使用
cookie-parser中间件用来对cookie进行解析,主要包括普通cookie的解析和签名cookie的解析。
-
简单用法
最简单的使用就是cookie的设置与解析,cookie的设置使用res.cookie方法,cookie的解析使用cookie-parser中间件
cookie-parser中间件 需要导入,不能直接使用
1 // 导入express 2 const express=require('express') 3 // 导入cookie中间件 4 const cookieParser = require('cookie-parser'); 5 6 const app = express(); 7 // 使用cookie-parser解析客户端传入的cookie 加密解密 8 app.use(cookieParser()); 9 // 向客户端发送cookie 10 app.get('/send',(req,res)=>{ 11 res.cookie('name','nihao',{maxAge:60*1000}) 12 res.send('向客户端发送cookie') 13 }) 14 // 接收服务器端传入的cookie 15 app.get('/receive',(req,res)=>{ 16 // cookies 是保存前面所有的cookie 17 // res.send('接收到的cookie-->'+req.cookies.name) 18 19 }) 20 21 22 app.listen( 3000,()=>{ 23 console.log(`serve running at http://localhost:3000`) 24 })
-
cookie签名、解析
出于安全的考虑,我们通常需要对cookie进行签名
主要要注意一下几点:
cookieParser
初始化时,传入secret(参数)
作为签名的秘钥。- 设置cookie时,将
signed
设置为true
,表示对cookie进行签名。 - 获取cookie时,可以同时通过
req.cookies
,也可以通过req.signedCookies
获取。
1 // 导入express 2 const express=require('express') 3 // 导入cookie中间件 4 const cookieParser = require('cookie-parser'); 5 6 const app = express(); 7 // 使用cookie-parser解析客户端传入的cookie 加密解密 8 app.use(cookieParser('aaa')); //secret 9 // 向客户端发送cookie 10 app.get('/send',(req,res)=>{ 11 res.cookie('name','nihao',{maxAge:60*1000,signed:true}) 12 res.send('向客户端发送cookie') 13 }) 14 // 接收服务器端传入的cookie 15 app.get('/receive',(req,res)=>{ 16 // cookies 是保存前面所有的cookie 17 res.send('接收到的cookie-->'+req.signedCookies.name) 18 19 }) 20 21 22 app.listen( 3000,()=>{ 23 console.log(`serve running at http://localhost:3000`) 24 })