Search code examples
javaspringresttemplate

How to deal with multiple ClientHttpRequestInterceptors in Spring 4


In RestTemplate, I have configured two ClientHttpRequestInterceptor (one for BasicAuthorization and another for Token based authentication.

From client side how I ask RestTemplate to use the correct ClientHttpRequestInterceptor to execute the API call.

Some API calls require BasicAuthorization to work. (For Ex: if the URL starts with "/admin" require BasicAuthorization, others require Token based Authentication)

How I can achieve this in Spring 4?


Solution

  • You could use two instances of RestTemplate, one for Basic auth and one for Token auth.

    @Bean
    @Qualifier("authRestTemplate")
    public RestTemplate getAuthTemplate{
        // create rest template, add auth interceptor
    }
    
    @Bean
    @Qualifier("tokenRestTemplate")
    public RestTemplate getTokenTemplate{
        // create rest template, add token interceptor
    }
    

    Then, when autowiring the RestTemplate, use the desired @Qualifier

    @Autowired
    @Qualifier("authRestTemplate")
    private RestTemplate authTemplate;
    
    @Autowired
    @Qualifier("tokenRestTemplate")
    private RestTemplate tokenTemplate;
    

    Another option would be adding two ClientHttpRequestInterceptor to the RestTemplate

    class BasicAuthInterceptor implements ClientHttpRequestInterceptor {
    
        private final AuthService authService;
    
        public BasicAuthHeaderInterceptor(AuthService authService) {
            this.authService = authService;
        }
    
        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
            if(isApplicable(request)){
                String token = Base64Utils.encodeToString((authService.getUsername() + ":" + authService.getpassword()).getBytes(Charset.forName("UTF-8")));
                request.getHeaders().add("Authorization", "Basic " + token);
            }
            return execution.execute(request, body);
        }
    
    }
    
    class TokenInterceptor implements ClientHttpRequestInterceptor {
    
        private final AuthService authService;
    
        public TokenHeaderInterceptor(AuthService authService) {
            this.authService = authService;
        }
    
        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
            if(isApplicable(request)){
                request.getHeaders().add("Authorization", "Bearer " + tokenService.getToken());
            }
            return execution.execute(request, body);
        }
    
    }
    

    Then, add the two interceptors to the RestTemplate

    @Bean
    public RestTemplate restTemplate(){
        RestTemplate template = new RestTemplate();
    
        template.getInterceptors().add(new BasicAuthInterceptor(authService));
        template.getInterceptors().add(new TokenInterceptor(authService));
    
        return template;
    }