【问题标题】:Best way to propagate credentials between micro services using spring-session使用 spring-session 在微服务之间传播凭据的最佳方法
【发布时间】:2015-08-07 10:10:15
【问题描述】:

我们使用的架构与this great guide on spring.io 中描述的架构非常相似。我们的网关处理身份验证,会话使用 spring-session 存储在 Redis 中。我们微服务的端点是安全的,也使用 spring-session。

在一个微服务中,我需要调用另一个微服务的端点。我通过发现客户端轻松获取 URL,但我需要提供凭据,我不确定实现该目标的最佳方法。

我正在考虑从HttpRequest中获取SESSION cookie,将其存储在某种线程局部变量或请求范围bean中,并在RestTemplate中使用它来调用第二个微服务。我需要这个请求范围的 bean,因为 RestTemplate 将在服务层中使用,即不在 MVC 控制器中,并且我不想用从 cookie 中获得的会话标识符污染我的服务层方法。

有没有更好的方法来满足这种需求? Spring Cloud 中是否已经对此提供了一些支持?

非常感谢您的意见

【问题讨论】:

  • Spring Cloud 中对此没有任何预烘焙支持。

标签: spring-cloud spring-session


【解决方案1】:

此时访问 Spring Session id 最简单的方法是使用RequestContextHolder.getRequestAttributes().getId()。一旦您有权访问它,您就可以编写自定义 ClientHttpRequestInterceptor 以在请求中包含会话 ID:

public SpringSessionClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
            throws IOException {
        boolean isMyService = ...;

        // very important not to send the session id to external services
        if(isMyService) {
            request.getHeaders().add("x-auth-token", RequestContextHolder.getRequestAttributes().getId());
        }
    }
}

然后,当您创建 RestTemplate 时,请确保添加 SpringSessionClientHttpRequestInterceptor。

RestTemplate rest = new RestTemplate();
rest.getInterceptors().add(new SpringSessionClientHttpRequestInterceptor());

【讨论】:

  • 谢谢 Rob,这很有帮助。我无法让它与 x-auth-token 一起使用,但添加一个值为 RequestContextHolder.getRequestAttributes().getSessionId() 的 SESSION cookie 工作正常。
  • 如果要使用 x-auth-token 标头,请确保自定义接收令牌的应用程序以使用 HeaderHttpSessionStrategy。见docs.spring.io/spring-session/docs/current/reference/html5/…
【解决方案2】:

我有一个类似的场景,我还需要在RestTemplate 中传递 CSRF 令牌。我知道您不想在控制器中实现它,但也许它会提供一些额外的见解(因为这个问题帮助我解决了这个问题)。以下是我在控制器中实现它的方式:

@RequestMapping(value = "/assets/download", method = RequestMethod.POST, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<Resource> downloadAssets(HttpSession session, @RequestBody SelectedAssets selectedAssets){
    ...
    ...

    CsrfToken token = (CsrfToken) session.getAttribute("org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN");  

    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.set("Cookie", "SESSION=" + session.getId() + "; XSRF-TOKEN=" + token.getToken());
    headers.set("X-XSRF-TOKEN", token.getToken());
    HttpEntity<SelectedAssets> selectedAssetsEntity = new HttpEntity<>(selectedAssets, headers);
    ResponseEntity<JobResponse> jobResponseResponseEntity = restTemplate.postForEntity("http://localhost:8102/jobs/package", selectedAssetsEntity, JobResponse.class);

    ...
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-01
    • 2017-12-13
    • 2020-01-15
    • 2021-12-06
    • 1970-01-01
    • 2020-07-21
    • 2022-09-28
    • 1970-01-01
    相关资源
    最近更新 更多