针对上面的问题,你在实际的开发过程中是否也有同样的疑问?
首先明确一点,这里有一个认知上的错误,access_token和refresh_token是OAuth2规范的内容,不是jwt规范的部分,jwt只是定义了一个token的编码加密解密方式,并不限制如何使用这个token。OAuth2是一种认证规范,其中包括有两个token:refresh_token和access_token,很多实践中这两个token是使用jwt来构建的,也可以使用其他方式构建这两个token,对于Oauth2来说只要两个能识别用户登录状态的字符串就好,并不理会是什么方式构建的。再说OAuth2规范为什么需要两个token。OAuth2定义了资源服务器和授权服务器,第一次认证向授权服务器提交用户名和密码获得两个token,然后访问资源服务器获取资源使用access_token, 资源服务器通常不太可以信任,所以不能给他知道refresh_token免得他自己跑去授权服务器提权,但是它需要access_token去找授权服务器认证客户端的身份(也可能不用找授权服务器,取决于认证的方案)。等access_token失效了,客户端又需要使用refreash_token去授权服务器获取新的access_token来访问资源服务器。在生产实践中很多系统往往简化了OAuth2的认证,把资源服务器和授权服务器合并了。在复杂的环境中资源服务器和授权服务器是由不同团队负责,甚至是不同的公司维护以至于相互并不信任,所以需要两个token来分别访问。
上面是较官方的陈述,可能很多人没有太理解,我就使用较通俗的内容翻译下。
系统前后端正常的流程是:用户使用用户名和密码成功登录系统后,系统会同时返回access_token和refresh_token,在后面的所有正常的接口请求时,必须携带刚才系统颁发的正确的access_token的值才能正常请求到系统服务端对应的逻辑,否则前端请求无法对服务端进行有效的交互。而对于这种正常的请求,接口是不需要携带refresh_token的,refresh_token的用处只是在当access_token有效期快要失效的时候,前端使用这个refresh_token请求对应的后台接口来换取新的acceess_token来保证接口的正常请求。
其实上面的流程很简单,如果将此种情况放到更大的情况下以及考虑到jwt的特有特性,有些隐藏的问题就会被放大。
在一般的JWT的常规架构中,已经发放出去的访问令牌是无法撤销和回收的。这也是JWT的显著特点之一,因为JWT本身就是一个去中心化的东西,谁获得了tokn,准就有权限访问。而缺点之一就是没办法直接实现token有效期刷新和token失效。只要客户端特有的访问令牌不过期,那么就可以访问对应的资源。
为什么无法撤销?
因为HTTP是无状态的,所以每一个请求都要带着访问令牌。
访问令牌一旦泄漏怎么办?
因为无法撤销,没有办法阻止非法得到访问令牌的人访问系统。
那么降低风险的办法就是让访问令牌的有效朗变短,令牌被非法窃取后也会很快就失效了从而导致其无法继续访问系统。
设置一个超长有效期的访问令牌,或者用访问令牌去续新的访问令牌,都会触发上面的安全问题。这引起另一个问题:刷新令牌不也是JWT吗,不是有一样的安全问题吗?
上面内容已经提到了,对应刷新令牌refresh_token又不是每个请求都需要携带,也只是在刷新令牌的时候才会用一次,说到底是为了系统的安全性,因为是无法保证access_token不被窃取。
同样,access_token使用的次数越多被窃取概率越大,过期时间越长也就越危险,所以,access_token传输次数越少越好,有效期越短越好。可是实际需要频繁使用access_token怎么办呢?对应的解决办法就是给两个token,一个token拿来频繁使用(有效期短)就是access_token了,另外一个token藏起来(有效期长)就是refresh_token了,即使频繁使用的acccess_token被窃取了,因为其有效期短,造成的损失也可能小一些。当频繁使用的access_token过期时,可以通过藏起来的refresh_token隐蔽的生成一个新的短期access_token拿出去使用,这样相对的会更安全些。
上面这种设计思想,现在也被大家广泛采纳,比如抖音,钉钉 这种都是在平台注册个app应用,然后给appkey和appsercret 然后用这两个参数换取accesstoken和refreshtoken ,accesstoken一般一两个小时失效,refreshtoken时间很长,调用平台api就要用accesstoken 快过期了就用refreshtoken去调刷新接口重新获取新的accesstoken和refreshtoken解决续期的问题,至于为什么用双token是因为accesstoken频繁使用,一旦泄露会有安全隐患,而refreshtoken只有刷新时候才用,调用次数很低,减少了被盗取的风险。
以上为全部内容。