Token授权

概述

前后端分离的项目一般有两个token:访问令牌(Access Token) 和 刷新令牌(Refresh Token)

Access Token

Access Token是登录后的令牌,用于访问业务API,每次请求都会携带;有效期较短,通常只有几分钟或几小时;即使被被截获,也能最大化的限制滥用。Access Token存储在浏览器的localStoragesessionStorage中,容易造到XSS跨站脚本攻击。

Refresh Token

Refresh Token用于获取新的Access Token。刷新Token有效期较长,且只在后端使用,一般存储在 HTTP-only 的 Cookie 中。

HTTP-only 的 Cookie 只能通过 HTTP/S 协议访问,客户端脚本(如 JavaScript)无法访问;因此其安全性能较高,能减少XSS跨站脚本攻击的威胁。HTTP-only Cookie 在每次请求中都会被浏览器自动附加到请求头中。即使用户在浏览器中禁用了普通 Cookie,HTTP-only Cookie 仍然会被发送,因为 HTTP-only Cookie 的是由服务器端设置。禁用普通 Cookie 主要是限制了 JavaScript 访问和修改 Cookie 的能力。浏览器在接收到HTTP-only这样的 Cookie 后,本身就会禁止脚本访问该 Cookie,因此在禁用普通 Cookie 的情况下,攻击者将更难以通过恶意脚本来窃取或篡改用户的 Cookie。

手机APP通常使用安全存储(Secure Storage)来存储Refresh Token,并且只有在Access Token过期时,都会在请求中携带Refresh Token;

Token安全

Token失窃通常由以下几方面造成:

1. 未使用https协议,导致请求头中的token暴露在网络中

2. 保存在客户端的token被恶意程序窃取

综上所述,在使用https协议的情况下,如何保护存储在客户端的token至关重要。如果网站使用了有漏洞的三方库,或网页被注入恶意代码,都会导致token失窃;但使用HTTP-only Cookie可以直接禁止所有客户端代码访问Refresh token,从根本上解决了客户端token失窃的问题;但这也会导致正常的业务代码无法访问token,所以才有了两个token的出现。如果给Access Token设置较短的有效期,就算客户端Access Token失窃,也能极大的限制滥用。因此,在保证Refresh token安全的情况下,为Access Token设置较短的有效期,理论上可以保持用户永远处于登录状态,就像微信、支付宝一样。

扩展:浏览器只信任服务端设置的HTTP-only Cookie,以其它任何方式给请求设置的HTTP-only Cookie都无法得到浏览器的信任,也就不会携带到服务端去;况且在浏览器中任何脚本都无法读写HTTP-only Cookie。但可以通过java、python等语言构造一个请求,并在请求中设置HTTP-only Cookie;但这又引出另一个话题,即如何防止用户浏览器之外构造请求访问服务端。

受信TOken

1. 业务每次请求时都去用户中心去验证token,这是一个性能很低的方式;并且随着业务系统越来越多,用户中心的带宽和性能压力会逐渐上升;

2. 为了提升业务系统的鉴权性能、减轻用户中心系统的请求压力,业务系统使用jwt标准的token自行鉴权;

3. JWT标准是一个通用的、被广泛接受的规范,由专业的安全专家和社区进行设计和审查,因此使用标准的JWT库通常是更安全和可靠的选择。

4. MD5是已经被证明存在安全漏洞,可能会遭受碰撞攻击,因此,建议使用更安全的哈希函数,如SHA-256,来验证数据的完整性;

5. 业务服务通过JWT验证token有效性,一旦token过期,则返回401;客户收到401后,自行去中心服务器刷新token。

前后端分离Token

由于前后端不同域,因此无法在用户中心的登录接口中为业务系统设置httpOnly cookie;安全的做法如下:

1. 业务系统调用用户中心完成登录后,立即将用户中心返回的jwt token上报到业务系统;

2. 业务系统通过专门的接口收到上报的jwt token后,验证jwt token的开始有效期是否在3分钟内;如果在3分钟内,则立即生成一个刷新token,并保存到httpOnly Cookie中;

3. 之后,业务系统的所有接口请求都要同时验证jwt token和刷新token,两者缺一不可。

上述方式在申请到jwt token后,立即生成刷新token,并在接口请求时验证刷新token;此方式相当于登录后立即将登录设备和jwt token绑定在一起;如此一来,就算jwt token失窃也无法单独使用,因为必须配合刷新token一起使用;而刷新token存储在于httpOnly Cookie中,其安全级别非常高,基本不会失窃。

在此策略之上,再将token的有效期设置为2小时,超过2小时后,调用用户中心重新获取jwt token。原则上,jwt token中不应该保存可变的用户信息,例如,用户名称、手机号等;因为不安全,也不可靠。因为jwt token中可变的信息并不可靠,可能随时被用户修改。

防止用户在浏览器之外通过构造请求来访问服务端接口

1. 在Nginx中限制单IP的接口访问频次;

2. 对于限量或付费的接口,无需进行额外限制;

3. 对于无限量但要避免机器访问的接口,可在一定时间或token刷新次数后进行人机验证;


举报

© 著作权归作者所有


1