一, 为什么 Cookie 需要防篡改
为什么要做 Cookie 防篡改, 一个重要原因是 Cookie 中存储有判断当前登陆用户会话信息 (Session) 的会话票据 - SessionID 和一些用户信息.
当发起一个 HTTP 请求, HTTP 请求头会带上 Cookie,Cookie 里面就包含有 SessionID.
后端服务根据 SessionID, 去获取当前的会话信息. 如果会话信息存在, 则代表该请求的用户已经登陆.
服务器根据登陆用户的权限, 返回请求的数据到浏览器端.
因为 Cookie 是存储在客户端, 用户可以随意修改. 所以, 存在一定的安全隐患.
二, 例子
用户 wall 在浏览器端输入用户名密码, 发起 POST 请求到后端服务器. 后端服务器验证合法, 返回 Response, 并 Set-Cookie 为
- sessionid=***;username=wall;
- .
浏览器端在接收到 HTTP 响应后, 发现 Set-Cookie, 将其存入本地内存或硬盘中.
浏览器端再次发起请求, 带上 Cookie 信息
sessionid=***;username=wall;
, 请求修改自己的头像信息.
服务器根据 sessionid 验证当前用户已登陆, 根据 username, 查找数据库中的对应数据, 修改头像信息.
如果当前用户知道 username 的作用, 修改 username=pony. 再次发起请求, 则服务器接收到请求后, 会去修改 username 为 pony 的数据.
这样, 就暴露出数据被恶意篡改的风险.
三, 防篡改签名
服务器为每个 Cookie 项生成签名. 如果用户篡改 Cookie, 则与签名无法对应上. 以此, 来判断数据是否被篡改.
原理如下:
服务端提供一个签名生成算法 secret
根据方法生成签名
secret(wall)=34Yult8i
将生成的签名放入对应的 Cookie 项
username=wall|34Yult8i
. 其中, 内容和签名用 | 隔开.
服务端根据接收到的内容和签名, 校验内容是否被篡改.
举个栗子:
比如服务器接收到请求中的 Cookie 项
username=pony|34Yult8i
, 然后使用签名生成算法 secret(pony)=666.
算法得到的签名
666
和请求中数据的签名不一致, 则证明数据被篡改.
四, 敏感数据的保护
鉴于 Cookie 的安全性隐患, 敏感数据都应避免存储在 Cookie.
应该根据 SessionID, 将敏感数据存储在后端. 取数据时, 根据 SessionID 去后端服务器获取即可.
另外, 对一些重要的 Cookie 项, 应该生成对应的签名, 来防止被恶意篡改.
来源: https://www.cnblogs.com/walls/p/9070166.html