BFF转微服务架构下的认证方案选型:客户端凭证VS令牌转发
我之前在AWS上搭建过类似的BFF+微服务架构,也纠结过这两个方案的取舍,结合实际落地的经验,给你拆解一下两个方案的问题和优化方向,以及更适合生产环境的折中思路:
方案1:BFF统一网关模式的优缺与优化
核心优势
- 职责清晰:BFF作为统一入口,集中处理认证、权限校验逻辑,微服务只需要专注业务实现,不用关心用户身份相关的逻辑,团队协作成本低。
- 信任模型简单:所有微服务只需要信任BFF,不用和Cognito直接交互,减少了服务间的依赖。
你担心的风险:客户端凭证权限过大
这个顾虑完全正确——生产环境中给BFF配置全权限的客户端凭证确实是高风险操作,一旦BFF被攻破,攻击者可以直接操作所有微服务的全部功能。但这个问题是可以通过优化解决的:
- 细粒度权限控制:给BFF的客户端凭证配置最小必要权限,比如只能调用用户服务的「权限查询接口」、产品服务的「指定业务操作接口」,而不是开放所有接口的访问权限。在AWS Cognito中,可以通过自定义Scopes或者IAM策略来实现这一点。
- 先验令牌有效性:BFF收到前端的Cognito令牌后,必须先验证令牌的合法性(包括签名、过期时间、受众Audience、Issuer),不能直接跳过这一步去查权限。可以用Cognito提供的JWKS端点来验证JWT的签名,确保令牌是合法有效的。
- 权限结果缓存:BFF可以把用户的权限信息缓存一段时间(比如15分钟),减少对用户服务的重复调用,同时避免频繁查询带来的性能损耗。
方案2:令牌转发+微服务自主校验的优缺与优化
核心优势
- 权限校验去中心化:每个微服务自主控制权限逻辑,不会因为BFF的故障导致整个系统的权限校验失效,微服务的独立性更强。
- 避免BFF成为单点故障:如果BFF只是做令牌转发,那么它的逻辑更简单,故障影响范围更小。
你担心的两个问题
1. 令牌转发导致用户直接调用微服务
这个风险可以通过网络隔离彻底解决:在AWS上,把所有微服务部署在私有VPC子网中,不对外暴露公网IP,只允许BFF所在的子网访问微服务。前端只能通过公网访问BFF,就算用户拿到令牌,也无法直接连接到微服务,因为网络上是不通的。
2. 权限校验逻辑分散
可以把权限校验的逻辑抽成公共组件/SDK,比如开发一个基于用户服务的权限校验SDK,产品服务和其他微服务直接引入这个SDK,不用每个服务都重复写调用用户服务的代码。这样既保证了权限逻辑的一致性,又减少了重复开发。
另外,令牌转发时要注意:前端传给BFF的如果是Cognito的ID Token,不要直接转发给微服务——ID Token是给前端用来展示用户信息的,不应该作为后端服务的认证凭证。应该让前端传Access Token,微服务拿到Access Token后,通过Cognito的JWKS端点验证令牌的合法性,再去查权限。
中间路线:兼顾安全与简洁的折中方案
如果觉得上面两个方案都有瑕疵,其实可以结合两者的优点,设计一个更安全的方案:
- 前端用户登录Cognito后,把Access Token传给BFF。
- BFF验证Access Token的有效性后,调用AWS Cognito的
AssumeRoleWithWebIdentityAPI,获取一个针对该用户的短期IAM临时凭证(有效期可以设置为15-30分钟)。 - BFF用这个临时凭证调用产品服务,产品服务通过IAM的权限策略来验证该用户是否有执行操作的权限(也可以结合用户服务的细粒度权限)。
- 临时凭证是和用户身份绑定的,权限也是最小必要的,就算泄露了,有效期短,风险可控;同时BFF不用持有长期的高权限客户端凭证,安全性更高。
或者另一种思路:BFF验证用户令牌后,生成一个内部专用的JWT(包含用户ID、权限列表、有效期),用BFF的私钥签名,然后把这个内部JWT传给微服务。微服务用BFF的公钥验证签名后,直接解析JWT里的权限信息,不用再调用用户服务。这种方式既避免了令牌转发的风险,又减少了服务间的调用。
最终选型建议
- 如果你的团队规模较小,业务逻辑相对简单,优先选优化后的方案1:给BFF配置细粒度的客户端凭证,加上令牌验证和权限缓存,这样维护成本低,逻辑清晰,适合快速迭代。
- 如果你的团队规模较大,微服务数量多,需要每个服务自主控制权限,优先选优化后的方案2:配合网络隔离和公共权限SDK,解决令牌转发和逻辑分散的问题,适合大型分布式系统。
- 如果对安全性要求极高,建议选中间路线的临时凭证方案:用AWS的IAM临时凭证来替代长期客户端凭证,既保证安全,又兼顾了系统的可扩展性。
最后补充一点:不管选哪个方案,都要做好日志审计——把所有的认证、权限校验操作都记录下来,方便后续的安全排查和合规审计。在AWS上可以用CloudWatch Logs来收集和分析这些日志。




