• spring feign https配置

    前两天需要通过springboot-feign来调用一个https的外部服务接口,因此要实现feign-client的SSL设置。 feign执行http请求通常会调用feign.Client接口的实现。这个接口的默认实现类Default提供了添加SSL配置的构造器: 简单介绍下构造器参数中用到的SSL相关的接口: SSLSocketFactory:SSLSocket工厂;SSLSocket扩展了Socket并提供使用SSL或TLS协议的安全套接字。这种套接字是正常的流套接字,但是它们在基础网络传输协议(如TCP)上添加了安全保护层。 HostnameVerifier:实现主机名验证功能;在握手期间,如果URL的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口实现程序来确定是否应该允许此连接,如果回调内实现不恰当,默认接受所有域名,则有安全风险。 默认使用的Client实例的两个构造参数的值都是null。我们需要在配置类中创建使用SSL的Client实例,这里参考了默认的配置类FeignClientsConfiguration: 代码中使用了SSLContext的getSocketFactory方法来创建 SSLSocketFactory对象。在创建SSLContext对象时,通过(chain, authType) -> true指定了SSL信任策略,即:不做任何处理,信任全部请求。 另一个HostnameVerifier类型的参数使用了一个实现类NoopHostnameVerifier的实例,作用是关闭主机名验证功能,并且永远不会抛出SSLException。 最后将配置添加到FeignClient注解上即可: 如代码中所示可以为configuration项一次指定多个配置类。这里的第一个配置类是spring默认提供的配置类。 另外,如需要创建Client的Bean实例,在使用Eureka的情况下,应选择LoadBalancerFeignClient的对象,不然会产生诸如无法解析host之类的问题。 就这样了。

    [阅读更多...]
  • 解决PKIX:unable to find valid certification path to requested target

    遇到了“unable to find valid certification path to requested target”这样的问题。 错误详情如下: 从异常信息中可以看到错误是因为找不到证书导致的。 解决方案有两个。 正常的方案当然是找到证书并安装证书。这种方案能找到一大把,在这里不做展开。 说个暴力的方案:取消证书认证,信任所有请求链接。 使用的工具是fluent-http-client,maven地址是: 首先创建一个自定义的HttpClient实例。这个实例将信任所有的请求链接。实例详情如下: 注意代码中的两处注释,是关键。 然后绑定新创建的实例,执行一个Get请求:就这样。 #######

    [阅读更多...]
  • 关于https的一个错误

    前两天我维护的服务出了一个问题,在请求一个连接时发生了Exception: 异常大致说的是在进行https请求时,验证证书出了问题。 服务基于JDK1.6,使用httpclient(版本是4.5.1)发送请求,调用的URL是https://talkingdata.qccr.com。 异常中的信息说的是请求的地址(talkingdata.qccr.com)与获得的证书中的hostName(*.qichechaoren.com)不符,因此在SSLPeerUnverifiedException.verifyHostname()方法中抛出了异常。但是在浏览器中发送请求或者是通过curl命令都是能够访问的。最让人郁闷的是在我的机器上使用原程序执行调用也没有报异常;把相关的程序封装成jar扔到服务器上调用还是正常的。 想了一段时间,在curl命令中添加了SSL信息,像这样: 2和3分别表示用的是sslv2和sslv3。果然报错了。后来又发现了SSL的实现还有TLS,试着使用TLS协议请求是正确的: 之前没有想到过SSL协议这里,打开浏览器看了一下这个地址的证书果然是TLS的: 看样子是在处理TLS请求时出了问题。 接下来就是定位问题的出处了。既然程序是可以正常执行的,那么就极有可能是出在容器上。把相关的程序重新封装下扔到jetty中执行果然报异常了。当时认为问题就是出在jetty上了,可能是服务与容器间存在类冲突。容器的类是不好轻易换的,只好改程序了。原程序是这样子的: 需要调整的就是SSL的支持那一块。将对https的验证强行去掉好了。只需要改一处: 现在请求是可以不报异常了。因为所有关于hostName的验证都是返回true 隔天和同事说起这件事,同事提供了一个信息:生产环境上的jetty容器使用的jdk和系统jre是不一样的…. jetty容器使用的是jdk1.6,服务器jre是1.7,我开发用的机器jdk是1.8。当时居然没有想到这上头。问题有可能是出在jre上啊。所以最后将jetty使用的jdk版本升级以后就好了。 今天也尝试着定位问题发生的具体位置来着,后来发现是在handshake的时候,jdk1.6和jdk1.7会返回不同的证书信息。更具体的信息想要获取就有些困难了,因为相关的部分代码是不开源的。 之前本以为是这个地址的证书是采用的TLS1.2,而jdk1.6的大部分版本都是不支持TLS1.2的。后来使用工具分析了请求的地址,发现支持的协议包括TLS1.0、TLS1.1、TLS1.2。而TLS1.0在JDK1.1的时候就已经支持了。 已经在这个问题上用了四分之一个周末的时间了,还有其他事情要做,目前只好暂时放下了。 一个SSL分析的网址:https://www.ssllabs.com/ssltest/analyze.html。 openJdk关于TLS1.2的BUG清单:https://bugs.openjdk.java.net/browse/JDK-6916074。 ##############

    [阅读更多...]