两种思路
通常微服务的认证和授权思路有两种:
- 所有的认证授权都由一个独立的用户认证授权服务器负责,它只负责发放Token,然后网关只负责转发请求到各个微服务模块,由微服务各个模块自行对Token进行校验处理。
- 另一种是网关不但承担了流量转发作用,还承担认证授权流程,当前请求的认证信息由网关中继给下游服务器。
第一种非常简单,而且我在多个微服务项目中都是这样设计的。如果你从来没有设计过,我其实建议按这个思路去做,你只需要搞一个负责管理用户、角色权限的服务器,其它的微服务模块都作为资源服务器自行和这个用户授权服务器进行交互,加上三户模型体系就足以应对各种场景了。
第二种结合了OAuth2体系,网关不仅仅承担流量转发功能,认证授权也是在网关层处理的,令牌会中继给下游服务。这种模式下需要搭建一个UAA(User Account And Authentication)服务。它非常灵活,它可以管理用户,也可以让受信任的客户端自己管理用户,它只负责对客户端进行认证(区别于用户认证)和对客户端进行授权。目前使用OAuth2对微服务进行安全体系建设的都使用这种方式。
接下来分享一下我在第二种思路上的成果。
Spring Cloud Gateway 结合OAuth2提供UAA服务
用的技术有:
- Spring Cloud Gateway
- Spring Authorization Server
- Spring Security 5.0 OAuth2 Client
- OIDC 1.0
大致的思路
UAA服务器自然由 Spring Authorization Server承担。它负责整个用户的管理,当然你还可以分离一个专门的用户服务器,只不过UAA需要通过Spring Cloud OpenFeign和用户服务通信;另外它还是一个OAuth2授权服务器,管理OAuth2客户端,处理OAuth2授权。重点来了,网关Gateway需要作为OAuth2客户端注册到UAA服务器,并作为一个OAuth2客户端。
微服务应用
当User Agent(浏览器、APP)通过网关请求资源时:
上面执行的是一个标准的OAuth2授权码流程,Spring Cloud Gateway会把用户引导到UAA服务器的登录接口去登录。
终端用户登录后进行授权确认,注意看F12的链路。
用户确认
用户勾选授权并确认后,成功访问到了资源,同样看调用的链路。
成功访问资源
授权确认提交后,再次重定向到OAuth2授权码登录流程,最终获取了资源。
我们看最终/res/foo的请求细节,居然没有携带Token也拿到了用户的所有权限。
这都是网关令牌中继的功劳,前端应用很好地屏蔽了JWT令牌。
如果有多个Gateway节点和UAA节点,可能要结合Spring Session去实现分布式Session以及对一些客户端信息、用户信息进行分布式管理。
总结
通过上面流程的介绍,动手能力很强的小伙伴应该能实现相关的功能了。