Best way to propagate credentials between micro services using spring-session

▼魔方 西西 提交于 2019-12-05 14:59:48

At this time the easiest way to access the Spring Session id is using RequestContextHolder.getRequestAttributes().getId(). Once you have access to that you can write a custom ClientHttpRequestInterceptor to include the session id in requests:

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());
        }
    }
}

Then when you create your RestTemplate make sure to add SpringSessionClientHttpRequestInterceptor.

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

I had a similar scenario where I also needed to pass the CSRF token in the RestTemplate. I know you don't want to implement it in the controller but maybe it will give some additional insight (as this question helped me solve the issue). Here is how I implemented it in my controller:

@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);

    ...
    ...
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!