在 spring oauth2(SSO 应用程序)中在拦截器和业务层之间共享用户上下文

share user context between interceptor and business layer in spring oauth2 (sso application)

我有一个问题来自阅读 Spring user 和 oauth2 的大量示例,但在一些基本概念上仍然失败,也许有人可以指出我好的 directions/examples 或信息阅读。

所以我正在尝试构建一个基于休息的 API 应用程序。 要访问端点,它们将受到 JWT 令牌的保护,并且想法是该令牌用于跨多个其他应用程序的 SSO。

我最初的想法是拥有一些处理令牌的身份验证过滤器拦截器,这样我就可以存储我可能需要的任何其他信息,然后在我服务的实际业务层中使用该用户。 我已经实现了一些实现 Filter 的 AuthenticationFiler 在我从我的令牌存储中读取令牌访问后,我可以获得额外的信息。

现在我的第一个问题实际上是大多数示例都是从 login/logout 页面开始的,因为我有更多的 API 设置,所以我真的没有那个流程。

其次,似乎大多数时候获取用户的方式是从委托人 (SecurityContextHolder.getContext().getAuthentication().getPrinciple()) 这样的事情但我的委托人总是空的,不确定如果这是因为我真的不知道这是否是因为有状态与无状态或排序。

所以我最大的问题是了解如何在我的安全拦截器和我的业务层之间共享用户详细信息。也许这个问题本身与 spring 无关,我缺少更多的基本知识,但也许有人可以给我一些指示。

这是我的身份验证过滤器,我想知道的是如何创建用户实例,就像我可以使用 MDC 存储用户信息一样。 理想情况下,我想在那里创建一个用户实例并将其传递给业务层。我可以用 Autowire 做到这一点吗?

@Component
@Order(Ordered.LOWEST_PRECEDENCE)
public class AuthenticationFilter implements Filter {

  @Autowired
  TokenStore tokenStore;

  @Autowired
  JwtAccessTokenConverter accessTokenConverter;


  @Override
  public void init(FilterConfig filterConfig) {

  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication != null) {
      if (authentication instanceof OAuth2Authentication) {
        OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) authentication;
        OAuth2AuthenticationDetails oauth2AuthenticationDetails = (OAuth2AuthenticationDetails)oAuth2Authentication.getDetails();
        OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(oauth2AuthenticationDetails.getTokenValue());
        Object decodedDetails = oauth2AuthenticationDetails.getDecodedDetails();
        Map<String, Object> additionalInformation = oAuth2AccessToken.getAdditionalInformation();
        MDC.put("sub", additionalInformation.get("sub").toString());
        MDC.put("preferred_username", additionalInformation.get("preferred_username").toString());
      }
    }
    try {
      chain.doFilter(request, response);
    }
    finally {
      MDC.remove("sub");
      MDC.remove("preferred_username");
    }
  }

  @Override
  public void destroy() {

  }
}

不确定这是否是我的误解,但我认为我正在寻找的是依赖注入。

我想以某种方式创建一个新的用户 Bean,将其填充到我的过滤器中并在其他地方使用它。 我想我可以在我的业务层中做一个@autowire 并将其设置在过滤器中并在业务层中使用它吗? 这是一个错误的模式吗?

据我了解你的架构,你正在开发这个:

  • RestAPI,应该受JWT保护。

你想要这个:

  • 访问业务层传入 JWT 中接收到的用户信息。

如果以上两个假设都是正确的,您应该阅读 spring 如何在其微服务架构中执行此操作。阅读此内容以快速入门:

https://dzone.com/articles/json-web-tokens-with-spring-cloud-microservices

希望对您有所帮助。