如何在Spring Boot微服务应用程序之间传递用户ID

时间:2017-04-04 13:37:07

标签: java spring authentication oauth-2.0 microservices

我有三项服务:

  1. 验证(OAuth2令牌配置和用户名+密码,没有别的)
  2. 用户相关资源(链接设备,出生日期等)
  3. 域名数据
  4. 这三个都是Spring Boot应用程序。使用JDBC令牌存储通过OAuth2令牌配置完成身份验证。登录,获取令牌效果很好,从其他两个资源服务器中的任何一个请求数据也很有效。但是我对我的表现并不满意,因为它看起来有点笨拙:

    资源服务器上的所有数据都通过服务器端生成的用户ID链接到用户。如果用户想要更改他/她的用户名,我认为将其链接到用户名是一个坏主意。现在,我获取用户ID的方式很简单:

    LocalDateTime

    方法@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 ... } 将Auth服务器上的整个User对象作为地图返回 - 因为这是我在 application.properties 文件中链接它的方式:

    getDetails

    但我不能让自己对这个解决方案感到满意,因为:

    1. 所有面向用户的方法都必须从这个解析开始,即使我把它变成一个单独的类,它对于每个方法仍然是相同的两行。
    2. 我觉得这些方法甚至不应该将对象security.oauth2.resource.userInfoUri=http://localhost:9000/api-auth/user 作为输入 - 它应该在上面的一层而不是在这里(虽然可能是我错误的感觉)。
    3. 我的问题是 - 我可以更有效地完成吗?以更清洁和可持续的方式?

      我想:

      OAuth2Authentication authentication

      肯定依赖于发送此数据的客户端 - 这必须来自Auth服务器。

      我(迄今为止失败)的想法:

      1. JWT令牌使用 - 由于我正在使用JDBC令牌存储并且似乎与JWT不兼容而失败。此外,JWT令牌不能被撤销,因为它们没有被存储,必须通过短期访问/刷新令牌来处理。但如果没有别的办法,我对这种方法持开放态度。
      2. 过滤器 - 我最喜欢的,我认为这就是它,但我无法使它工作 - 我收到的请求是@RequestMapping(method = RequestMethod.GET) public ResponseEntity<SampleData> getData(String userId) { // interact with data with the userId } 并解析数据。但后来我无法将解析后的对象直接分发到控制器中。这似乎是解决方案,但我想这可能不适合这个。
      3. 我接近这个完全错误了还是我错过了一些自动解决这个问题的Spring Boot细节?

1 个答案:

答案 0 :(得分:1)

我会将选项2与OncePerRequestFilter一起使用。您可以解析一次,如果创建新线程,则将结果存储在ThreadLocalInheritableThreadLocal中。

然后可以从控制器访问线程本地数据,甚至可以从服务层更深入地访问。

ThreadLocal

  

每个线程都拥有对其线程局部变量副本的隐式引用,只要该线程处于活动状态并且可以访问ThreadLocal实例;一个线程消失后,它的所有线程局部实例副本都会被垃圾收集(除非存在对这些副本的其他引用)。