Позвоните в WS с фальшивым клиентом и сертификатом

Я борюсь с основными швами, но не могу понять это. У меня есть приложение для весенней загрузки, которое должно отображать URL-адрес отдыха.

Я делаю это так:

@RestController
@RequestMapping(value = "/api")
public class MdmhController {

    @Resource
    private MdmhClient mdmhClient;


    @RequestMapping(
            method = RequestMethod.GET,
            value = "/myEntityNames",
            produces = { MediaType.APPLICATION_JSON_UTF8_VALUE }
    )
    ResponseEntity<Iterable<String>> getMyEntityNames() {

        MyEntity[] myEntities =
                mdmhClient.getMyentitis();

        Set<String> myEntityNames= new HashSet<>();
        for (MyEntity me : myEntities ) {
            myEntityNames.add(me.getName());
        }
        return new ResponseEntity<Iterable<String>>(myEntityNames, HttpStatus.OK);
    }
}

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

@Import(FeignClientsConfiguration.class)
@Component
public class MdmhClientImpl implements MdmhClient {

    private final Decoder decoder;
    private final Encoder encoder;

    private  MdmhClient mdmhClient;

    @Value("${mdmh.serviceId}") // injected by sprins yaml e.g. url-to-service.com
    private String mdmhServiceId;

    @Autowired
    public MdmhClientImpl(
            final Decoder decoder, final Encoder encoder) {
        this.decoder = decoder;
        this.encoder = encoder;
    }

    @Override
    public MyEntity[] getMyEntities() {

        if (mdmhClient == null) {
            mdmhClient = Feign.builder()
                    .encoder(encoder)
                    .decoder(decoder)
                    .client(new Client.Default(TrustingSSLSocketFactory.get(), null))
                    .target(MdmhClient.class, "https://" + mdmhServiceId);
        }
        return mdmhClient.getMyEntity();
    }
}

Интерфейс выглядит так:

@RestController
@RequestMapping(value = "/api")
public interface MdmhClient {

    @RequestLine("GET mdmh/service/v2/myentities")
    @Headers({ "accept: application/json" })
    MyEntity[] getMyEntities();
}

Когда MdmhClient выдает исключение при вызове mdmhClient.getEntity():

SunCertPathBuilderException: unable to find valid certification path to requested target.

Я знаю, что для решения этой проблемы мне нужно импортировать сертификат в jre. Я запускаю Intellij IDE и устанавливаю путь к jdk моего проекта:

C:\Program Files\Java\jdk1.8.0_65

Я также получил доступ к веб-сервису через firefox:

https://url-to-service.com/mdmh/service/v2/myentities

и загрузил сертификат, который я импортировал:

C:\Program Files\Java\jdk1.8.0_65\jre\lib\security\cacerts

Но я все равно получаю сообщение об ошибке. От разочарования импортировал сертификат на все установленные jdks, все те же.

Я нашел: https://github.com/OpenFeign/feign/blob/master/core/src/test/java/feign/client/TrustingSSLSocketFactory.java

и добавил его в мой MdmhClient, например:

@Override
public MyEntity[] getMyEntities() {

    if (mdmhClient == null) {
        Client client = new Client.Default(
                TrustingSSLSocketFactory.get(),
                new HostnameVerifier() {
                    @Override
                    public boolean verify(String s, SSLSession sslSession) {
                        return true;
                    }
                });
        mdmhClient = Feign.builder()
                .encoder(encoder)
                .decoder(decoder)
                .client(new Client.Default(TrustingSSLSocketFactory.get(), null))
                .target(MdmhClient.class, "https://" + mdmhServiceId);
    }
    return mdmhClient.getMyEntities();
}

после этого я получаю ответ AccessDenied от вызываемой службы.

ERROR [081-exec-3] 17.08.17 08:26:28.868  org.apache.juli.logging.DirectJDKLog@log: Servlet.service() for servlet [dispatcherServlet] in context with path [/lic] threw exception [Request processing failed; nested exception is feign.FeignException: status 403 reading MdmhClient#getFamilyVersions(); content:
<HTML><HEAD>
<TITLE>Access Denied</TITLE>
</HEAD>
<BODY>
<FONT f...

Но я на 100% уверен, что аутентификация мне не нужна. Поскольку я могу ввести URL-адрес в браузер, не изменяя заголовки, и получить результат.

Надеюсь, вы сможете мне помочь или подскажете, как решить эту проблему.

Спасибо


person kism3t    schedule 17.08.2017    source источник
comment
Вам следует удалить аннотации к вашему MdmhClient интерфейсу   -  person Sonata    schedule 21.08.2017


Ответы (2)


Похоже, ваш клиент обращается к сервису через прокси-сервер. Прокси-сервер требует аутентификации и, таким образом, отвечает 403 и использует другой сертификат (цепочку), поэтому импорт сертификата, полученного от веб-службы, не помогает.

person Sonata    schedule 21.08.2017

Вы можете попробовать следующие методы переопределения

@Bean
public Client feignClient()
{
    Client trustSSLSockets = new Client.Default(getSSLSocketFactory(), new NoopHostnameVerifier());
    return trustSSLSockets;
}


private SSLSocketFactory getSSLSocketFactory() {
    try {
        TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        };

        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
        return sslContext.getSocketFactory();
    } catch (Exception exception) {
    }
    return null;
}
person eranda.del    schedule 22.07.2019