如何在 Spring 引导微服务应用程序之间传递用户 ID
How to communicate user ID between Spring Boot microservice applications
我有三个服务:
- Auth(提供 OAuth2 令牌和用户名 + 密码,仅此而已)
- 用户相关资源(链接设备、出生日期等)
- 域数据
它们三个都是 Spring 启动应用程序。身份验证是通过 OAuth2 令牌提供完成的,使用 JDBC 令牌存储。登录、获取令牌效果很好,从其他两个资源服务器中的任何一个请求数据也效果很好。但是我对自己的做法并不满意,因为它看起来有点笨拙:
资源服务器上的所有数据都通过服务器端生成的用户ID链接到用户。如果用户想要更改 his/her 用户名,我认为将它链接到用户名不是一个好主意。现在,我获取用户 ID 的方式很简单:
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<SampleData> getData(OAuth2Authentication authentication) {
Authentication auth = authentication.getUserAuthentication();
final Map<String, Object> map = (Map) auth.getDetails();
// parse user data from the map ...
}
方法 getDetails
returns Auth 服务器上的整个用户对象作为地图 - 因为这是我在 application.properties[=53 中链接它的方式=] 文件:
security.oauth2.resource.userInfoUri=http://localhost:9000/api-auth/user
但我无法接受这个解决方案,因为:
- 所有面向用户的方法都必须从这个解析开始,即使在我把它变成一个单独的 class 之后,每个方法仍然是相同的两行。
- 我觉得这些方法甚至不应该将对象
OAuth2Authentication authentication
作为输入 - 它应该在上面的一层而不是这里(虽然这可能是我的错误感觉)。
我的问题是 - 我可以更有效地做到这一点吗?以更清洁和可持续的方式?
我想要:
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<SampleData> getData(String userId) {
// interact with data with the userId
}
绝对不取决于发送此数据的客户端 - 这必须来自 Auth 服务器。
我的(到目前为止失败的)想法:
- JWT 令牌使用 - 由于我正在使用 JDBC 令牌存储而失败,这似乎与 JWT 不兼容。此外,JWT 令牌无法撤销,因为它们未被存储并且必须通过短期 access/refresh 令牌进行处理。但如果没有别的办法,我对这种方法持开放态度。
- 过滤器 - 我最喜欢的,我以为就是这样,但我无法让它工作 - 我收到了请求,例如
OncePerRequestFilter
并解析数据。但是后来我无法将解析后的对象直接分发到控制器中。这似乎是解决方案,但我想这可能不是为了这个。
我的处理方法是完全错误的还是我遗漏了一些 Spring 自动解决此问题的引导细节?
我会使用选项 2 和 OncePerRequestFilter
。如果您创建新线程,您可以解析一次并将结果存储在 ThreadLocal
或 InheritableThreadLocal
中。
然后可以从您的控制器甚至更深的服务层访问线程本地数据。
Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).
我有三个服务:
- Auth(提供 OAuth2 令牌和用户名 + 密码,仅此而已)
- 用户相关资源(链接设备、出生日期等)
- 域数据
它们三个都是 Spring 启动应用程序。身份验证是通过 OAuth2 令牌提供完成的,使用 JDBC 令牌存储。登录、获取令牌效果很好,从其他两个资源服务器中的任何一个请求数据也效果很好。但是我对自己的做法并不满意,因为它看起来有点笨拙:
资源服务器上的所有数据都通过服务器端生成的用户ID链接到用户。如果用户想要更改 his/her 用户名,我认为将它链接到用户名不是一个好主意。现在,我获取用户 ID 的方式很简单:
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<SampleData> getData(OAuth2Authentication authentication) {
Authentication auth = authentication.getUserAuthentication();
final Map<String, Object> map = (Map) auth.getDetails();
// parse user data from the map ...
}
方法 getDetails
returns Auth 服务器上的整个用户对象作为地图 - 因为这是我在 application.properties[=53 中链接它的方式=] 文件:
security.oauth2.resource.userInfoUri=http://localhost:9000/api-auth/user
但我无法接受这个解决方案,因为:
- 所有面向用户的方法都必须从这个解析开始,即使在我把它变成一个单独的 class 之后,每个方法仍然是相同的两行。
- 我觉得这些方法甚至不应该将对象
OAuth2Authentication authentication
作为输入 - 它应该在上面的一层而不是这里(虽然这可能是我的错误感觉)。
我的问题是 - 我可以更有效地做到这一点吗?以更清洁和可持续的方式?
我想要:
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<SampleData> getData(String userId) {
// interact with data with the userId
}
绝对不取决于发送此数据的客户端 - 这必须来自 Auth 服务器。
我的(到目前为止失败的)想法:
- JWT 令牌使用 - 由于我正在使用 JDBC 令牌存储而失败,这似乎与 JWT 不兼容。此外,JWT 令牌无法撤销,因为它们未被存储并且必须通过短期 access/refresh 令牌进行处理。但如果没有别的办法,我对这种方法持开放态度。
- 过滤器 - 我最喜欢的,我以为就是这样,但我无法让它工作 - 我收到了请求,例如
OncePerRequestFilter
并解析数据。但是后来我无法将解析后的对象直接分发到控制器中。这似乎是解决方案,但我想这可能不是为了这个。
我的处理方法是完全错误的还是我遗漏了一些 Spring 自动解决此问题的引导细节?
我会使用选项 2 和 OncePerRequestFilter
。如果您创建新线程,您可以解析一次并将结果存储在 ThreadLocal
或 InheritableThreadLocal
中。
然后可以从您的控制器甚至更深的服务层访问线程本地数据。
Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).