Притворная конфигурация не используется - PullRequest
0 голосов
/ 20 апреля 2020

Я использую Feign в Spring Boot API, и я хотел бы настроить его следующим образом:

import feign.RequestInterceptor;
import feign.auth.BasicAuthRequestInterceptor;
import feign.codec.ErrorDecoder;
import feign.okhttp.OkHttpClient;
import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignClientConfiguration {

    @Bean
    public ErrorDecoder errorDecoder() {
        return new ErrorDecoder.Default();
    }

    @Bean
    public OkHttpClient client() {
        return new OkHttpClient();
    }

    @Bean
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> {
            requestTemplate.header("user", "some user");
            requestTemplate.header("password", "some password");
            requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
        };
    }


}

Проблема в том, что если я использую следующий код в службе, я получаю 401, кажется как будто данные аутентификации не были предоставлены:

        Feign.builder()
        .client(new OkHttpClient())
        .encoder(new GsonEncoder())
        .decoder(new GsonDecoder())
        .logger(new Slf4jLogger(Npa.class))
        .target(AClass.class, "https://some.website");

Если я просто добавлю одну строку, указав имя пользователя и пароль, она будет работать:

    Feign.builder()
    .client(new OkHttpClient())
    .encoder(new GsonEncoder())
    .decoder(new GsonDecoder())
    .logger(new Slf4jLogger(Npa.class))
    .requestInterceptor(new BasicAuthRequestInterceptor("some user", "some password"))
    .target(AClass.class, "https://some.website");

Я бы предпочел использовать конфигурацию, но я не могу понять, что неправильно в этом.

1 Ответ

0 голосов
/ 20 апреля 2020

Поскольку вы создали некоторые bean-компоненты, вам не нужно создавать их вручную снова на этапах компоновщика.

Псевдокласс, в котором вы можете создать своего симулированного клиента, может выглядеть следующим образом:

@Component
public class FeignClientFactory {

    @Autowired
    private ErrorDecoder errorDecoder;

    @Autowired
    private OkHttpClient client;

    @Autowired
    private RequestInterceptor requestInterceptor;

    public AClass getFeignClient() {
        return Feign.builder()
                .client(client)
                .encoder(new GsonEncoder())
                .decoder(new GsonDecoder())
                .logger(new Slf4jLogger(Npa.class))
                .requestInterceptor(requestInterceptor)
                .target(AClass.class, "https://some.website");
    }
}

Конечно, есть много вариантов, чтобы улучшить его. Например, вы можете создавать другие bean-компоненты (для кодировщиков, регистраторов и т. Д.) Или использовать стандартные (автоматически конфигурируемые).

Или вы можете сделать это в классе @Configuration, если вам нужен только один клиентский bean-компонент.

В случае перехватчиков запросов - есть еще один шаг построения .requestInterceptors, где вы можете передать их коллекцию.

РЕДАКТИРОВАТЬ: Для базовой аутентификации c вам не нужно иметь отдельные заголовки имени пользователя и пароля, а вместо этого один заголовок "Авторизация". Его значение должно выглядеть как «Basi c username: password», где часть «username: password» должна быть закодирована с Base64 ( link ).

Итак, в вашем классе @Configuration вы можете написать что-то вроде этого:

@Bean
public RequestInterceptor requestInterceptor() {
    return requestTemplate -> {
        String encodedCredentials = Base64.getEncoder()
            .encodeToString("some user:some password".getBytes());
        requestTemplate.header("Authorization", "Basic " + encodedCredentials);
        requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
    };
}

Затем вы можете использовать этот bean-компонент для построения клиента Feign, как я описал выше.

Другой вариант: Поскольку создание Заголовок авторизации является довольно распространенной задачей, BasicAuthRequestInterceptor был представлен Feign, который делает то же самое. Вы можете использовать его вместо этого. Итак, теперь в @Configuration классе вы можете создать два bean-компонента:

    @Bean
    @Qualifier("basicAuthRequestInterceptor")
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("some user","some password");
    }

    @Bean
    @Qualifier("customRequestInterceptor")
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> {
            requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
        };
    }

В этом случае вам нужно изменить метод построения клиентского симулятора, чтобы применить оба этих перехватчика:

@Component
public class FeignClientFactory {

    @Autowired
    private ErrorDecoder errorDecoder;

    @Autowired
    private OkHttpClient client;

    @Autowired
    @Qualifier("basicAuthRequestInterceptor")
    private RequestInterceptor basicAuthRequestInterceptor;

    @Autowired
    @Qualifier("customRequestInterceptor")
    private RequestInterceptor requestInterceptor;

    public AClass getFeignClient() {
        List<RequestInterceptor> requestInterceptors = new ArrayList<>();
        requestInterceptors.add(basicAuthRequestInterceptor);
        requestInterceptors.add(requestInterceptor);

        return Feign.builder()
                .client(client)
                .encoder(new GsonEncoder())
                .decoder(new GsonDecoder())
                .logger(new Slf4jLogger(Npa.class))
                .requestInterceptors(requestInterceptors)
                .target(AClass.class, "https://some.website");
    }
}
...