背景
从传统的单体应用转型Spring Cloud的朋友都在问我,Spring Cloud下的微服务权限怎么管?怎么设计比较合理?从大层面讲叫服务权限,往小处拆分,分别为三块:用户认证、用户权限、服务校验。前端
用户认证
传统的单体应用可能习惯了session的存在,而到了Spring cloud的微服务化后,session虽然能够采起分布式会话来解决,但终究不是上上策。开始有人推行Spring Cloud Security结合很好的OAuth2,后面为了优化OAuth 2中Access Token的存储问题,提升后端服务的可用性和扩展性,有了更好Token验证方式JWT(JSON Web Token)。这里要强调一点的是,OAuth2和JWT这两个根本没有可比性,是两个彻底不一样的东西。
OAuth2是一种受权框架,而JWT是一种认证协议git
OAuth2认证框架
OAuth2中包含四个角色:
资源拥有者(Resource Owner)
资源服务器(Resource Server)
受权服务器(Authorization Server)
客户端(Client)
OAuth2包含4种受权模式
受权码(认证码)模式 (Authorization code)
简化(隐形)模式 (Impilict
用户名密码模式 (Resource Owner Password Credential)
客户端模式 (Client Credential)
其中,OAuth2的运行流程以下图,摘自RFC 6749:github
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
咱们在Spring Cloud OAuth2中,全部访问微服务资源的请求都在Http Header中携带Token,被访问的服务接下来再去请求受权服务器验证Token的有效性,目前这种方式,咱们须要两次或者更屡次的请求,全部的Token有效性校验都落在的受权服务器上,对于咱们系统的水平扩展成为一个很是大的瓶颈。web
JWT认证协议
受权服务器将用户信息和受权范围序列化后放入一个JSON字符串,而后使用Base64进行编码,最终在受权服务器用私钥对这个字符串进行签名,获得一个JSON Web Token。后端
假设其余全部的资源服务器都将持有一个RSA公钥,当资源服务器接收到这个在Http Header中存有Token的请求,资源服务器就能够拿到这个Token,并验证它是否使用正确的私钥签名(是否通过受权服务器签名,也就是验签)。验签经过,反序列化后就拿到Toekn中包含的有效验证信息。api
其中,主体运做流程图以下:缓存
+-----------+ +-------------+
| | 1-Request Authorization | |
| |------------------------------------>| |
| | grant_type&username&password | |--+
| | |Authorization| | 2-Gen
| | |Service | | JWT
| | 3-Response Authorization | |<-+
| |<------------------------------------| Private Key |
| | access_token / refresh_token | |
| | token_type / expire_in | |
| Client | +-------------+
| |
| | +-------------+
| | 4-Request Resource | |
| |-----------------------------------> | |
| | Authorization: bearer Access Token | |--+
| | | Resource | | 5-Verify
| | | Service | | Token
| | 6-Response Resource | |<-+
| |<----------------------------------- | Public Key |
+-----------+ +-------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
经过上述的方式,咱们能够很好地完成服务化后的用户认证。安全
用户权限
传统的单体应用的权限拦截,你们都喜欢shiro,并且用的颇为顺手。但是一旦拆分后,这权限开始分散在各个API了,shiro还好使吗?笔者在项目中,并无用shiro。先后端分离后,交互都是token,后端的服务无状态化,前端按钮资源化,权限放哪儿管好使?服务器
抽象与设计
在介绍灵活的核心设计前,先给你们普及一个入门的概念:RBAC(Role-Based Access Control,基于角色的访问控制),就是用户经过角色与权限进行关联。简单地说,一个用户拥有若干角色,每个角色拥有若干权限。session
RBAC实际上是一种分析模型,主要分为:基本模型RBAC0(Core RBAC)、角色分层模型RBAC1(Hierarchal RBAC)、角色限制模型RBAC2(Constraint RBAC)和统一模型RBAC3(Combines RBAC)。
更多详情你们能够了解:RBAC权限模型
核心UML
这是笔者经过多种业务场景后抽象的RBAC关系图
类说明
Group
群或组,拥有必定数量权限的集合,亦能够是权限的载体。
子类:User(用户)、Role(角色)、Position(岗位)、Unit(部门),经过用户的特定构成,造成不一样业务场景的群或组,而经过对群或组的父类受权,完成了用户的权限获取。
Permission
权限,拥有必定数量资源的集成,亦能够是资源的载体。
Resources
权限下有资源,资源的来源有:Menu(菜单)、Button(动做权限)、页面元素(按钮、tab等)、数据权限等
Program
程序,相关权限控制的呈现载体,能够在多个菜单中挂载。
常见web程序基本构成
模型与微服务的关系
若是把Spring Cloud服务化后的全部api接口都定义为上文的Resources,那么咱们能够看到这么一个状况。
好比一个用户的增删改查,咱们的页面会这么作
页面元素 资源编码 资源URI 资源请求方式
查询 user_btn_get /api/user/{id} GET
增长 user_btn_add /api/user POST
编辑 user_btn_edit /api/user/{id} PUT
删除 user_btn_del /api/user/{id} DELETE
在抽象成上述的映射关系后,咱们的先后端的资源有了参照,咱们对于用户组的权限受权就容易了。好比我授予一个用户增长、删除权限。在前端咱们只须要检验该资源编码的有无就能够控制按钮的显示和隐藏,而在后端咱们只须要统一拦截判断该用户是否具备URI和对应请求方式便可。
至于权限的统一拦截是放置在Zuul这个网关上,仍是落在具体的后端服务的拦截器上(Filter、Inteceptor),均可以垂手可得地实现。不在局限于代码的侵入性。放置Zuul流程图以下:
要是权限的统一拦截放置在Zuul上,会有一个问题,那就是后端服务安不安全,服务只须要经过注册中心,便可对其余服务进行调用。这里就涉及到后面的第三个模块,服务之间的鉴权。
服务之间的鉴权
由于咱们都知道服务之间开源经过注册中心寻到客户端后,直接远程过程调用的。对于生产上的各个服务,一个个敏感性的接口,咱们更是须要加以保护。主题的流程以下图:
笔者的实现方式是基于Spring Cloud的FeignClient Inteceprot(自动申请服务token、传递当前上下文)和Mvc Inteceptor(服务token校验、更新当前上下文)来实现,从而对服务的安全性作进一步保护。
结合Spring Cloud的特性后,总体流程图以下:
优化点
虽然经过上述的用户合法性检验、用户权限拦截以及服务之间的鉴权,保证了Api接口的安全性,可是其间的Http访问频率是比较高的,请求数量上来的时候,慢的问题是就会特别明显。能够考虑必定的优化策略,好比用户权限缓存、服务受权信息的派发与混存、定时刷新服务鉴权Token等。
结语上述是笔者在项目里的大致思路,有兴趣的朋友能够借鉴个人开源项目,欢迎star: - gitchina:https://gitee.com/minull/ace-security(Jwt、用户权限) - github:https://github.com/wxiaoqi/ace-security - gitchina:http://git.oschina.net/geek_qi/ace-gate(服务鉴权)