用户使用用户名密码登录后服务器给客户端返回一个 Token(通常是 UUID),并将 Token-UserId 以键值对的形式存放在缓存服务器中。服务端接收到请求后进行 Token 验证,如果 Token 不存在,说明请求无效。Token 是客户端访问服务端的凭证。
用户每次请求都带上当前时间的时间戳 timestamp,服务端接收到 timestamp 后跟当前时间进行比对,如果时间差大于一定时间 (比如 5 分钟),则认为该请求失效。时间戳超时机制是防御 DOS 攻击的有效手段。
将 Token 和 时间戳 加上其他请求参数再用 MD5 或 SHA-1 算法 (可根据情况加点盐) 加密,加密后的数据就是本次请求的签名 sign,服务端接收到请求后以同样的算法得到签名,并跟当前的签名进行比对,如果不一样,说明参数被更改过,直接返回错误标识。签名机制保证了数据不会被篡改。
防止 token 被截取后在别的网络环境发出请求,在服务器通过请求 ip 与这个 ip 必须对上才能解密
客户端第一次访问时,将签名 sign 存放到缓存服务器中,超时时间设定为跟时间戳的超时时间一致,二者时间一致可以保证无论在 timestamp 限定时间内还是外 URL 都只能访问一次。如果有人使用同一个 URL 再次访问,如果发现缓存服务器中已经存在了本次签名,则拒绝服务。
如果在缓存中的签名失效的情况下,有人使用同一个 URL 再次访问,则会被时间戳超时机制拦截。这就是为什么要求时间戳的超时时间要设定为跟时间戳的超时时间一致。拒绝重复调用机制确保 URL 被别人截获了也无法使用 (如抓取数据)。
1、客户端通过用户名密码登录服务器并获取 Token
2、客户端生成时间戳 timestamp,并将 timestamp 作为其中一个参数
3、客户端将所有的参数,包括 Token 和 timestamp 按照自己的算法进行排序加密得到签名 sign
4、将 token、timestamp 和 sign 作为请求时必须携带的参数加在每个请求的 URL 后边 (http://url/request?token=2021×tamp=2021&sign=20212021)
5、服务端写一个过滤器对 token、timestamp 和 sign 进行验证,只有在 token 有效、timestamp 未超时、缓存服务器中不存在 sign 三种情况同时满足,本次请求才有效
A .如果有人劫持了请求,并对请求中的参数进行了修改,签名就无法通过;
B .如果有人使用已经劫持的 URL 进行 DOS 攻击,服务器则会因为缓存服务器中已经存在签名或时间戳超时而拒绝服务,所以 DOS 攻击也是不可能的;
C .如果签名算法和用户名密码都暴露了,那齐天大圣来了估计也不好使吧。。。。
最后说一句,所有的安全措施都用上的话有时候难免太过复杂,在实际项目中需要根据自身情况作出裁剪,比如可以只使用签名机制就可以保证信息不会被篡改,或者定向提供服务的时候只用 Token 机制就可以了。如何裁剪,全看项目实际情况和对接口安全性的要求~