如何在Kubernetes集群中的微服务之间进行JWT身份验证

时间:2019-11-25 07:19:57

标签: java authentication kubernetes jwt microservices

我们在kubeneters集群中有8个Java微服务相互通信。每个微服务都与身份验证库捆绑在一起,身份验证库针对向控制器的每个REST请求拦截并验证/更新JWT令牌。

场景: 从Frontend,我们第一次获得访问令牌,身份验证成功。可以说

  1. 前端使用访问令牌点击“微服务A”-成功
  2. “微服务A”内部通过restTemplate命中“微服务B”。 我的“微服务B”也需要登录用户详细信息。

问题:我必须将相同的访问令牌从“ A”传递到“ B”,但我无法在Controller / Service逻辑中获取访问令牌,而只能在正在验证令牌的过滤器中获取。通过在控制器的所有rest方法中添加以下参数,可以在Rest Controllers中获得令牌:

@RequestHeader (name="Authorization") String token

但是我不想采用这种方法,因为我必须将此令牌传递到任何地方直到结束,并且必须在所有APIS中声明此参数。

我想通过传递身份验证对象从TokenStore获得令牌。我们正在使用Oauth2,我检查了库中的代码,有很多tokenStore提供程序。

在DefaultTokenServices.java类中,我正在呼叫

Authentication auth = SecurityContextHolder.getContext().getAuthentication() // Passed this auth to tokenStore
String token = tokenStore.getAccessToken(auth).getValue(); // NullPointerException

我的代码正在通过JWTTokenStore提供程序,该提供程序返回null。我检查了一下,有一个名为InMemoryTokenStore.class的提供程序,它实际上从商店中提取了令牌。但是我的流程并没有涉及到内存实现。

有什么方法可以让我事后获得令牌,而无需通过参数在控制器中获取令牌吗?或如何启用/使用inMemoryTokenStore?

还推荐一些更好的kubernetes互通身份验证吗?

TIA

1 个答案:

答案 0 :(得分:1)

您似乎正在使用Spring(和Spring Security),所以我认为文档的相关部分是Bearer Token Propagation上的部分。

它的建议是使用WebClient(从Spring 5开始,建议RestTemplate的替代品)使用提供的ServletBearerExchangeFilterFunction将JWT令牌从传入请求自动传播到传出请求:

@Bean
public WebClient rest() {
    return WebClient.builder()
            .filter(new ServletBearerExchangeFilterFunction())
            .build();
}

RestTemplate上,文档说:

  

“目前尚无对RestTemplate的专门支持,但您可以使用自己的拦截器非常简单地实现传播”

,并提供以下示例:

@Bean
RestTemplate rest() {
    RestTemplate rest = new RestTemplate();
    rest.getInterceptors().add((request, body, execution) -> {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            return execution.execute(request, body);
        }

        if (!(authentication.getCredentials() instanceof AbstractOAuth2Token)) {
            return execution.execute(request, body);
        }

        AbstractOAuth2Token token = (AbstractOAuth2Token) authentication.getCredentials();
        request.getHeaders().setBearerAuth(token.getTokenValue());
        return execution.execute(request, body);
    });
    return rest;
}

如果您要尝试传播令牌,我不认为您需要查看TokenStore。请记住,与JWT相关的所有内容都应位于令牌本身内。 (这就是为什么the doc for the JwtTokenStore解释说它实际上不存储任何内容,而是从令牌中提取信息的原因,并且对于某些方法(包括您正在调用的getAccessToken()方法)将返回null。)