一、OAuth2认证框架
资源的请求携带Token,被访问的服务接下来再去请求授权服务器验证Token的有效性,目前这种方式,我们需要两次或者更多次的请求,所有的Token有效性校验都落在的授权服务器上,对于我们系统的水平扩展成为一个非常大的瓶颈。
OAuth2中包含四个角色:
资源拥有者(Resource Owner)
资源服务器(Resource Server)
授权服务器(Authorization Server)
客户端(Client)OAuth2包含4种授权模式:
授权码(认证码)模式 (Authorization code)
简化(隐形)模式 (Impilict
用户名密码模式 (Resource Owner Password Credential)
客户端模式 (Client Credential)
二、JWT认证协议
授权服务器将用户信息和授权范围序列化后放入一个JSON字符串,然后使用Base64进行编码,最终在授权服务器用私钥对这个字符串进行签名,得到一个JSON Web Token
- 优点
- 体积小,因而传输速度快
- 传输方式多样,可以通过URL/POST参数/HTTP头部等方式传输
- 严格的结构化。它自身(在 payload 中)就包含了所有与用户相关的验证消息,如用户可访问路由、访问有效期等信息,服务器无需再去连接数据库验证信息的有效性,并且 payload 支持为你的应用而定制化。
- 支持跨域验证,可以应用于单点登录。
-
存在的问题
JWT 自身(在 payload 中)就包含了所有与用户相关的验证消息,所以通常情况下不需要保存。这种设计存在几个问题:
- 1、Token不能撤销--客户端重置密码后之前的JWT依然可以使用(JWT 并没有过期或者失效
- 2、不支持refresh token,JWT过期后需要执行登录授权的完整流程
- 3、无法知道用户签发了几个JWT
针对第一个问题,可能的解决方法有:
- 保存JWT到数据库(或Redis),这样可以针对每个JWT单独校验
- 在重置密码等需要作废之前全部JWT时,把操作时间点记录到数据库(或Redis),校验JWT时同时判断此JWT创建之后有没有过重置密码等类似操作,如果有校验不通过
当然,这种解决方法都会多一次数据库请求,JWT自身可校验的优势会有所减少,同时也会影响认证效率。
这篇文章主要介绍解决第二个问题(不支持refresh token)的思路。
-
refresh token
refresh token是OAuth2 认证中的一个概念,和OAuth2 的access token 一起生成,表示更新令牌,过期所需时间比access toen 要长,可以用来获取下一次的access token。
如果JWT 需要添加 refresh token支持,refresh token需要满足的条件有一下几项:
- 和JWT一起生成返回给客户端
- 有实效时间,有效时间比JWT要长
- 只能用来换取下一次JWT,不能用于访问认证
- 不能重复使用(可选)
refresh token 获取流程
refresh token 使用流程
三、用户权限
shiro
传统的单体应用的权限拦截,大家都喜欢shiro。抽象设计
RBAC(Role-Based Access Control,基于角色的访问控制):
就是用户通过角色与权限进行关联。简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。
RBAC其实是一种分析模型,主要分为:基本模型RBAC0(Core RBAC)、角色分层模型RBAC1(Hierarchal RBAC)、角色限制模型RBAC2(Constraint RBAC)和统一模型RBAC3(Combines RBAC)。微服务鉴权
-
统一拦截放置在Zuul网关上,或者落在具体的后端服务的拦截器上(Filter、Inteceptor),都可以轻而易举地实现。不在局限于代码的侵入性。
-
基于Spring Cloud的FeignClient Inteceprot(自动申请服务token、传递当前上下文)和Mvc Inteceptor(服务token校验、更新当前上下文)来实现,从而对服务的安全性做进一步保护。