我已经使用 TokenRelay 过滤器通过 Spring Webflux 实现了前端后端 (BFF) 架构。我的前端使用 cookie 作为身份验证机制与 BFF 进行通信,BFF 从 Cognito 获取 JWT 令牌(或存储在 Spring 会话中,不确定。这对我来说很神奇)并将其在标头中发送到资源服务器。这里,BFF 节点作为机密的 oauth2 客户端工作,浏览器不需要存储任何 JWT 令牌或类似令牌。
作为一名开发人员,这对于我来说是透明地完成的。它配置正确并且工作没有任何问题。如果我从前端向 https://bff-url/api/users/{user-id} 发出请求,它就会起作用,自动重定向到用户微服务并将令牌附加到标头中。
但是,让我们考虑一个不在任何资源服务器(微服务)中的端点。该端点位于 BFF 中。
此端点 URL 为 https://bff-url/api/auth/me。我定义如下:
@RestController
@RequestMapping("/api/auth")
public class CurrentUserController {
public CurrentUserController() {
}
@GetMapping("/me")
@ResponseBody
public Mono<UserResponseDTO> getCurrentUser(Authentication authentication) {
String userId = ((DefaultOidcUser)authentication.getPrincipal()).getClaim("custom:userId");
// TODO call to users service users with this userId
return Mono.empty();
}
}
我只想从会话中获取 id(我明白了)并像往常一样调用用户服务。我不知道哪种方法最好:
我对根据 Spring 指南的任何其他方法持开放态度,因为我不是 Spring 专家,而且我可能遗漏了一些东西。
BFF 从 Cognito 获取 JWT 令牌(或存储在 Spring 会话中,不确定。这对我来说很神奇)
两者:BFF 是配置为使用授权代码流的 OAuth2 客户端(Spring Security 措辞中的
oauth2Login
)=> 这是它最初从授权服务器获取令牌的方式(可以使用刷新令牌流获取更多令牌)。然后它将这些令牌存储在会话中。因此,对于向 BFF 发出进一步请求,将在会话中读取令牌(除非它已过期或将在下一分钟内过期)。
我对根据 Spring 指南的任何其他方法持开放态度,因为我不是 Spring 专家,而且我可能遗漏了一些东西。
简单的方法是仅将 BFF 用于路由目的(动态调整会话/承载授权),并将此
/me
托管在用户服务中。由于 TokenRelay
为当前用户附加访问令牌,下游资源服务器中所需要做的就是反映访问令牌声明(全部或可能更好,只是必要的)。这就是我在这篇专门介绍 OAuth2 BFF 模式的 Baeldung 文章、这个其他项目以及实际上在许多其他地方所做的事情。
如果您更喜欢坚持使用 BFF 上的
/me
端点,有两个选项(但没有一个像上面的那样简单且可扩展):
ReactiveOAuth2AuthorizedClientManager
获取访问令牌以授权对用户服务的请求,然后解析答案以构建 UserDto (但是,为什么不使用带有 TokenRelay
过滤器的到用户服务的网关路由呢?)