Reputation: 7654
I have two Feign clients in Spring Boot doing different things, but would like them to be authenticated differently.
@FeignClient(
name = "...",
url = "${url1}",
configuration = Config1.class
)
public interface Client1 {
@PostMapping(
path = "...",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
JsonNode doThing(@RequestBody JsonNode thing);
}
@FeignClient(
name = "...",
url = "${url2}",
configuration = Config2.class
)
public interface Client2 {
@PostMapping(
path = "...",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
JsonNode doThing(@RequestBody JsonNode thing);
}
They both need basic authentication, but different values for username and password. For that, I thought about having separate Config
classes to set their respective clients:
@Configuration
public class Client1 {
private final String user;
private final String password;
public Client1(final Config1 config) {
this.user = config.getUser();
this.password = config.getPassword();
}
@Bean(name = "client1")
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor(user, password);
}
}
@Configuration
public class Client2 {
private final String user;
private final String password;
public Client1(final Config2 config) {
this.user = config.getUser();
this.password = config.getPassword();
}
@Bean(name = "client2")
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor(user, password);
}
}
But my API is returning HTTP 4xx errors, as if the interceptor did not work at all. Can I get some pointers on setting this up properly?
(Notice that I gave those beans name
s, because they will otherwise conflict for DI.)
Upvotes: 5
Views: 6782
Reputation: 2576
I know this question is old, but it seems that it was lacking an actual working response.
I managed to achieve this doing the following:
@Configuration
public class ClientAConfig {
@Bean(name = "clientARequestInterceptor")
public RequestInterceptor clientARequestInterceptor() {
return requestTemplate -> {
requestTemplate.header("Authorization", "Bearer tokenA");
};
}
}
and a similar one with different content for ClientBConfig
@FeignClient(name = "ClientAClient", url = "...", configuration = ClientAConfig.class)
public interface ClientAClient {...}
@FeignClient(name = "ClientBClient", url = "...", configuration = ClientBConfig.class)
public interface ClientBClient {...}
@Configuration
public class FeignConfiguration {
@Bean
public FeignClientConfigurer feignClientConfigurer() {
return new FeignClientConfigurer() {
@Override
public boolean inheritParentConfiguration() {
return false;
}
};
}
}
Upvotes: 2
Reputation: 21
Try remove @Configuration
annotation, and use ApplicationContext
to read configed properties:
// config
import feign.RequestInterceptor;
import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.context.annotation.Bean;
public class Client1 {
@Bean(name = "amapRequestInterceptor")
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
String user = SpringUtils.getProperty("client1.user", String.class, null);
String password = SpringUtils.getProperty("client1.password", String.class, null);
return new BasicAuthRequestInterceptor(user, password);
}
}
// SpringUtils
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
@Component
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
if (SpringUtils.applicationContext == null) {
SpringUtils.applicationContext = applicationContext;
}
}
public static <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
return applicationContext.getEnvironment().getProperty(key, targetType, defaultValue);
}
}
The problem in your code is feign will use all of RequestInterceptor
in application context so that Authorization
header is overwrite twice.
With @Configuration
removed, there is no RequestInterceptor in application context, feign will use RequestInterceptor
specified by @FeignClient
.
Upvotes: 0
Reputation: 126
I guess You have to remove the stereotype @Configuration
.
I actually came here during a search to a similar problem. I do have (same like You) two different configs. One FeignClient with and a second client without auth. But the second client is using both RequestInterceptors (I implemented a noop-RequestInterceptor just for logging).
Could You actually solve your problem?
Upvotes: 4