Web 应用通常借助 Cookie 保存会话信息,这些信息一般并不敏感,但必须防止用户伪造。
我们先来考察一个应用场景:用户登录,后端将登录用户账号保存在 Cookie 中;后续访问是,浏览器会带上该 Cookie ,后端据此检查登录是否合法。
这个场景存在一个非常严重的安全漏洞,用户可以伪造 Cookie !举个例子,他只要将 Cookie 改成我的账号 fasionchan ,就可以用我的账号来操作!那么,我们应该如何应对伪造数据呢?
您可能想到对数据进行加密,离开密钥就无法解读数据,更何况伪造?加密适用保护敏感数据,它可以同时实现 保密 和 防伪 两个目的。换句话讲,如果数据是不能被第三方获悉的,那就必须加密。
如果数据无须保密,而只想防伪,则可以为其计算 签名( signature )。例子中用 Cookie 保存的登录账号就是一个典型的例子,让第三方知道了也没什么影响,关键是要防止别人伪造。
那么,怎么对数据计算签名呢?
哈希
众所周知,对一段文本进行哈希,得到的哈希值可以作为文本的摘要,或者叫做信息指纹。哈希算法分很多种,常用的有 MD5 ,SHA 等等。同样的文本,用同样的的哈希算法,算出来的哈希值一定是一样的。以 MD5 为例:
|
|
签名密钥
您可能会说,哈希计算得到摘要也没啥用呀,别人照样可以这样做。没错,但我们再引入一个密钥,情况就不同了:
|
|
注意,这里密钥 secret 我随便用 123456 。密钥通常不能是简单的弱密码,不然很容易被破解。
现在将登录用户和签名拼在一起保存在 Cookie 中:
|
|
当后端服务器收到 Cookie 后,可以重新计算签名,以此进行验证:
|
|
如果计算得到的签名跟 Cookie 中保存的不一致,则说明数据是伪造的。由于第三方不掌握参与签名计算的 secret ,也就无法伪造数据。因此,secret 密钥必须妥善保管,绝对不能泄露。
弱密码
由于哈希算法可以暴力破解,如果黑客掌握了足够的数据和签名样本,而密钥又不够复杂,就很有可能被破解出来。举个例子,假设黑客有一个弱密码表,他只要逐个遍历验证,即可破解出密钥,如果密钥就在弱密码表里的话。
因此,密钥的选择必须足够复杂,绝对不能是一些常见的字符序列。
- 最好大小写字母、数字和符号都有;
- 长度足够长;
- 最好是随机生成的,没有规律的;
有效期
某些场景数据需要设置有效期,这时可以在数据的基础上加一个时间戳:
|
|
后端接到数据后,同样先将各个部分切分开,重新计算签名校验真伪。然后只需检查时间戳,即可判断数据是否还有效。需要特别注意,时间戳必须参与签名计算,否则别人可以伪造假的时间戳,从而绕过有效期限制。
【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注: