java - 使用 Feign 客户端和证书调用 WS

标签 java spring-boot ssl-certificate feign

我正在努力解决那些看似基本的问题,但无法理解它。我有一个 Spring Boot 应用程序,它应该公开一个休息网址。

我这样做是这样的:

@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访问了web服务:

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 输入到浏览器并获得结果。

我希望你能帮助我或给我一些如何解决这个问题的提示。

谢谢

最佳答案

看起来您的客户端正在通过代理服务器访问服务。代理服务器需要身份验证,因此响应 403 并使用不同的证书(链),因此导入从 Web 服务获取的证书没有帮助。

关于java - 使用 Feign 客户端和证书调用 WS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45728025/

相关文章:

javascript - 在 JavaScript GET 查询中发送 SSL 证书

java - 关于SymmetricDS Embedded的一些问题

java - 如何为具有 Webmethod 模式命名空间的 xml 创建 xsd

java - 如何更改页面 URL

java - Springboot 复选框值到 Controller

spring-boot - SpringBoot 错误 : Registered driver with driverClassName=oracle. jdbc.driver.OracleDriver was not found, 尝试直接实例化

java: 为什么我必须在构造函数的第一行写 super()

java - Spring-boot,JUnit 测试使用不同的配置文件

php - 如何在 PHP 中从 .pfx 证书获取 key.pem 和 crt.pem

ssl - 受信任的根 CA 是否应该成为证书链的一部分?