「码动四季·开源同行」go语言:如何设计基于 OAuth2 和 JWT 的认证与授权服务体系

张开发
2026/4/6 16:26:51 15 分钟阅读

分享文章

「码动四季·开源同行」go语言:如何设计基于 OAuth2 和 JWT 的认证与授权服务体系
在上文我们介绍了统一认证与授权在微服务架构中存在的一些必要性和挑战并介绍了3种主流的统一认证与授权方案包括 OAuth2、分布式 Session 和JWT。在本文我们将基于 OAuth2 和WT设计一个认证与授权服务让其为我们微服务的信息安全保驾护航。微服务架构的演进使得服务体系变得分散如果让每个微服务独立管理自身的用户信息容易造成信息隔离阻碍应用的发展因此将分散的认证和授权进行统一管理显得尤为必要。我们接下来就按照权限模型设计、OAuth2与JWT结合、Token 中继和整体结构设计这个思路来阐述统一认证与授权服务体系的设计。RBAC 和 ACL认证和授权本质上是对用户的访问权限进行控制关于权限系统的设计就不得不提及经典的RBACRole-BasedAccessControl模型即基于角色的访问控制模型。RBAC 模型将用户的操作过程抽象为 Who、What 和 How 这三者之间的关系换句话说就是 Who可以对 What 进行 How 的操作。RBAC 模型将用户通过角色与权限进行关联用户通过成为某一角色而获得该角色的权限一个用户可以有多个角色而每个角色又拥有多种权限。通过用户-角色-权限的授权模型大大简化了权限的管理。根据LIST提出的 RBAC96 模型RBAC 由4个概念性模型组成分别为RBACO作为基本模型定义了完全实现 RBAC 模型的系统的最低需求它是 RBAC 的核心所在;RBAC1在包含RBACO的基础上增加了角色分层的概念一个角色可以人另一个角色中继承权限;RBAC2同样在 RBACO的基础上引I入静态职责分离和动态职责分离它是 RBAC的约束模型RBAC3作为统一模型在基于RBAC0的基础上整合了RBAC1和RBAC2。RBAC96 模型族关系图如下所示:除了RBAC外还有一种比较流行的权限设计方案一一ACLAccessControlLists模型即访问控制列表。ACL的核心思想是将用户直接和权限关联这样就可以非常简单地完成访问控制。但是在权限过多时却又很容易造成授予权限时的复杂性访问控制列表的管理最终会演变成极为烦琐的工作。我们的实践将基于RBAC模型进行权限设计。不过在权限设计实践的过程中考虑到需求的差异性完全遵循RBAC 模型也许并不可取。我们应该根据自身业务需要适当地调整RBAC模型使其更加契合业务。为了简化权限设计方案便于实践的开展我们就基于RBACO模型描述的用户、角色、权限和会话关系设计如下的权限模型上图中分别有用户、角色和权限3个实体每个用户可以拥有多种角色每一种角色都是一定数量权限的集合它们之间通过关联表关联起来。当要授予某个用户部分权限时可以将对应的角色赋予用户比如在一个论坛系统中帖子管理员具备审核帖子、删除帖子等权限当有新的用户希望管理帖子时可以将帖子管理员的角色授予该用户这样他就具备了帖子管理的权限。OAuth2 和 JWTOAuth2作为当前授权行业的标准允许用户授权客户端访问它们存储在资源服务器上的信息。OAuth2中默认支持4种客户端类型分别为授权码类型、密码类型、简化类型和客户端类型对它们之间的区别了解不多的同学可以参考上一课时中对 OAuth2 的详细介绍。在微服务架构中会有多种多样的客户端通过网关接入系统中请求服务我们可以对这些客户端进行简单的分类包括第三方客户端应用和自家客户端应用两类。第三方客户端应用基本为外部系统希望请求本系统内的资源或者服务为了避免将系统内的用户信息泄漏给第三方客户端系统将通过授权码类型给这类客户端提供访问令牌。而对于自家客户端应用因为是可信任的客户端所以可以允许它们通过密码类型获取访问令牌即它们能够直接接触和保存用户的密码凭证等信息。JWT是高度紧凑和自包含的安全传输对象关于JWT头部、有效负载和签名的介绍可以参考上文。我们可以将WT用作访问令牌和刷新令牌的载体将签发JWT的 secret保存在授权服务器由授权服务器签发W样式的访问令牌。同时我们还可以将用户的相关信息比如用户ID、用户角色码和权限码等信息放到有效负载中当下游资源服务器使用用户的信息时可以直接从访问令牌中解析获取而无须重复查询数据库这就减少了请求消耗提升了访问效率。Token中继在微服务架构中各个微服务之间存在错综复杂的调用关系而且在调用过程中很可能需要获取用户的身份信息甚至部分接口还需要对用户拥有的权限进行鉴权。虽然我们可以在业务请求体中要求上游服务携带用户的相关信息然后在业务实现中根据用户信息去授权服务器查找用户对应的权限信息并进行鉴权操作但是这种方式对业务开发人员不友好需要他们在业务实现代码中频繁传递用户信息。同时这其中的部分通用鉴权行为完全可以通过资源服务器的方式实现从而减轻业务开发工作。我们可以将访问令牌在多个请求中进行传递也就是Token中继由资源服务器根据自身的认证和鉴权配置对访问令牌中用户身份和权限进行鉴权如下图所示如果访问令牌是M样式并且其中包含了用户身份信息和权限信息那么资源服务器就可以直接根据其内的信息进行鉴权操作从而避免频繁向权限系统请求用户的角色和权限信息。同时资源服务器应该具备Token中继的能力自动将请求中的访问令牌携带到下游让鉴权操作对业务开发人员透明。整体结构设计基于上面的介绍我们可以将微服务统一认证与授权服务体系设计为如下上述这个设计图的整体结构可描述为如下客户端作为用户的代理通过授权码类型或者密码类型向授权服务器请求访问令牌。客户端获取到对应的访问令牌后即可通过网关请求对应的微服务访问用户存储在系统中的资源。网关服务不仅仅起到为下游微服务做反向代理的作用还作为资源服务器去验证请求携带的访问令牌的有效性。JWT样式的访问令牌在颁发之后在JWT注册声明的有效时间到达之前访问令牌都会被认为是有效的。考虑到这个问题我们就需要在授权服务器中维护一个用户与有效访问令牌的映射在令牌主动失效时将该条映射关系主动删除以保证失效后的访问令牌不可用。因此网关在检验访问令牌的有效性时是需要请求授权服务器进行验证验证不通过的请求将被直接拒绝。授权服务器持有签发JWT样式访问令牌的 sercet在请求访问令牌时它会验证客户端的身份和携带的用户凭证或者授权码信息给通过验证的客户端颁发合法的访问令牌。同时授权服务器会接收网关关于令牌验证的请求通过合法的访问令牌的请求拒绝非法请求。除此之外授权服务器还具备权限管理的能力。业务服务在处理业务时可能需要获取当前访问用户的身份信息在进行敏感操作时还会对用户的角色和权限进行鉴权。我们可以通过Token中继机制在多个资源服务器之间传递访问令牌。由于访问令牌为MT样式资源服务器可以直接从访问令牌中解析出用户相关的角色和权限信息进行鉴权。小结统一认证与授权服务体系对于微服务架构来说是重要的基础设施它能够保护系统中的信息安全为系统带来统一的身份认证、第三方用户授权等基础能力提高系统的开放能力有利于构建业务生态体系。在本文我们基于OAuth2 和JWT设计了微服务架构下的认证与授权服务体系借助 RBAC 设计了系统的权限模型还讲解了Token中继机制如何在诸多资源服务器中简易地传递用户角色和权限信息。希望通过本文的学习能够加深你对微服务架构下统一认证与授权的设计与认知。后续我们将根据本课时中的设计实践如何通过Go实现授权服务器。

更多文章