当前位置: 首页 > 知识库问答 >
问题:

使用客户端和证书调用WS

黎腾
2023-03-14

我正在努力做一些基本的事情,但我的头脑还没有完全清醒过来。我有一个spring boot应用程序,它应该公开一个rest 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访问了webservice:

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();
}

在这之后,我从我的呼叫服务中得到一个拒绝访问的响应。

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...

但是我百分之百确定我不需要认证。因为我可以在不修改标题的情况下输入浏览器的网址并得到结果。

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

非常感谢。

共有2个答案

狄楷
2023-03-14

您可以尝试以下替代方法

@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;
}
裴俊迈
2023-03-14

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

 类似资料:
  • 我正在尝试使用一个Web服务,该服务要求开发人员作为参数的一部分传递签名证书。该服务在测试环境中运行良好,但是对于生产环境,除了签名证书外,还需要根证书才能成功访问该服务。这已经在《邮递员》中进行了测试,并取得了成功的结果。 当使用RestSharp库在C#代码中实现时,我得到如下所示的响应。 查询客户端响应日志:{“statusCode”:0,“statusDescription”:null,“

  • 问题内容: 我基本上需要确保对这项服务的要求。 已经为我提供了一个测试客户端和两个文件,以及,但是我不知道如何使用它们:我了解X509Certificate2类以某种方式涉及。 执行测试客户端的命令行如下: 它可以正常工作,因此我既可以看到服务,也应该正确配置服务本身。 我的C#客户端(针对.NET 2.0)使用普通的Web参考来执行请求: 服务器设置应正确设置。 我摸索了这些方法,但是我无法给出

  • 问题内容: 我想要求基于Java 1.7内置HttpsServer的服务器进行客户端证书认证。 我似乎找不到任何使服务器无法通过身份验证的方法。无论客户端证书是受信任的,未知的还是完全不存在的,它都会愉快地为所有旧客户端提供数据。 我对文档的阅读建议,如果不信任客户端,则设置HttpsParameters.setNeedClientAuth(true)应该会导致身份验证失败。我发现有类似问题的人的

  • 对于我们的指向站点VPN,我们希望创建一个根证书。因此我们可以为所有需要登录VPN的合作伙伴创建尽可能多的客户端证书。(Azure虚拟网络) 手工完成这件事很完美。我们生成一个作为根CA的证书(自签名)。我们可以在powershell中这样做:

  • 我有一个Java服务器应用程序,它通过TLS从GRPC客户端获取数据并在服务器上处理。现在我想使用多个客户端。要向客户端分配接收到的事件,我想读取客户端证书并使用证书的DN分配事件。如何获取客户端证书? 我发现这个构建服务器:https://github.com/grpc/grpc-java/blob/master/SECURITY.md#mutual-tls 然后你应该实现一个服务器拦截器 }

  • 问题内容: 我需要导入证书,以便向Spring Boot应用程序中的外部服务发出http请求。 我该如何设置Spring Boot来做到这一点? 那里有很多信息,但我发现所有这些都令人困惑。似乎我可能只需要创建类似“ truststore.jks”密钥库的内容并导入正确的证书,然后将一些条目添加到我的application.properties中即可。 问题答案: 打开您的终端或 回答所有问题。在