转载自:https://mp.weixin.qq.com/s/DkwfpZibKdllfm0lpxukWg
Token 能解决哪些问题呢?有如下几点:
-
Token 完全由应用管理,所以它可以避开同源策略。
-
Token 可以避免 CSRF 攻击(http://dwz.cn/7joLzx)。
-
Token 可以是无状态的,可以在多个服务间共享。
解决token失效问题
-
方案一:在服务器端保存 Token 状态,用户每次操作都会自动刷新(推迟) Token 的过期时间(Session也是这样干的)
同时通过把 Token 的过期时保存在缓存或者内存中,来提升效率
-
方案二: 使用 Refresh Token,它可以避免频繁的读写操作。 一旦 Token 过期,就反馈给前端,前端使用 Refresh Token 申请一个全新 Token 继续使用
有状态token: 在服务端需要保存并记录相关属性
无状态token: 把所有状态信息都附加在 Token上, 服务器就可以不保存。但是服务端仍然需要认证 Token 有效。
只要服务端能确认是自己签发的 Token,而且其信息未被改动过,那就可以认为 Token 有效——用“签名”作保证
签名: 一方签发,另一方验证,用非对称加密算法
改进: 签发和验证都是同一方,用 对称加密算法就行
改进: 对称加密算法除了加密,还带有还原加密内容的功能,而token验证不需要解密,使用摘要(散列)算法 HMAC更好。
JWT 已经定义了详细的规范,不需要自己实现
无状态token: 服务端虽然不保存有效的 Token 了,却需要保存未到期却已注销的 Token。
解决方法:
1. 在前端可控的情况下, 可以协商:前端一旦注销成功,就丢掉本地保存(比如保存在内存、Local Storage 等)的 Token 和 Refresh Token。
2. 如果前端不可控的情况, 需要尽量缩短 Token 的有效期,而且必须在用户主动注销的情况下让 Refresh Token 无效
在使用无状态 Token 的时候,有两点需要注意:
-
Refresh Token 有效时间较长,所以它应该在服务器端有状态,以增强安全性,确保用户注销时可控。
-
应该考虑使用二次认证来增强敏感操作的安全性。
分离认证服务
认证服务器和业务服务器采用相同的密钥和算法来来认证token( 建立在认证服务器信任业务服务器的前提下 )
不受信的业务服务器
认证服务器使用密钥 1 签发,业务服务器使用密钥 2 验证---- 非对称加密签名
认证服务器自己使用私钥对 Token 签名,公开公钥。信任这个认证服务器的业务服务器保存公钥,用于验证签名。
JWT 可使用 RSA(一种非对称加密算法)签名。
存在问题: 多个业务服务器之间使用相同的 Token 对用户来说是不安全的。
解决方案: 在认证服务器产生 Token 的时候,把使用该 Token 的业务服务器的信息记录在 Token 中。 另一个业务服务器 可以发现它不是自己应该验证的 Token
存在问题: 用户的不信任问题,用户无法确定自己要授权的应用是否安全
解决方案: 认证服器不公开公钥,要求业务服务先申请注册并通过审核, 只有通过审核的业务服务器才能得到认证服务为它 创建的,仅供它使用的公钥。(比如QQ互联)
如果用户还是不够信任,认证服务甚至可以问,某某某业务服务需要请求 A、B、C 三项个人数据,其中 A 是必须的,不然 它不工作,是否允许授权?如果你授权,我就把你授权的几项数据加密放在 Token 中……(就是token中的scope字段)
废话了这么多,有没有似曾相识……对了,这类似开放式 API 的认证过程。开放式 API 多采用 OAuth 认证,而关于 OAuth 的探讨资源非常丰富,这里就不深究了。