单独使用Feign 绕过ssl接口调用restful 接口

1.Spring boot 项目中的pom.xml 加入Feign的依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-jackson</artifactId>
            <version>11.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-slf4j</artifactId>
            <version>11.0</version>
        </dependency>

2.FeignClientHttpsNoSSLConfig 定义

在FeignClientHttpsNoSSLConfig中重写了Feign.Builderfeign.Client 的配置。其中指定了feign.Client 所使用的SSLSocketFactory
下面对各个类做一下简单介绍:

  • Feign.Builder:是feign.Client的建造者,用于建造feign.Client实例;
  • feign.Client:feign客户端,用于提交Http/Https请求;
  • Logger.Level:当前FeignClient日志输出级别;文章末尾有详细描述;
  • SSLSocketFactory:SSLSocket工厂;SSLSocket扩展了Socket并提供使用SSL或TLS协议的安全套接字。这种套接字是正常的流套接字,但是它们在基础网络传输协议(如TCP)上添加了安全保护层。
  • HostnameVerifier:实现主机名验证功能;在握手期间,如果URL的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口实现程序来确定是否应该允许此连接,如果回调内实现不恰当,默认接受所有域名,则有安全风险;
package com.huaun.tvm.feign;

import feign.Client;
import feign.Feign;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;



/**
 * @author :hongyan.xu
 * @date :Created in 2021/3/1 15:08
 * @description:feign绕过ssl调用https的接口配置
 * @modified By:
 * @version: $
 */
@Configuration
public class FeignClientHttpsNoSSLConfig {
    @Bean
    public Feign.Builder feignBuilder() {
        final Client trustSSLSockets = client();
        return Feign.builder().client(trustSSLSockets);
    }

    @Bean
    public Client client(){
        SSLContext ctx =null;
        try {
             ctx = SSLContext.getInstance("SSL");
            TxTrusManagers tm=new TxTrusManagers();
            ctx.init(null, new TrustManager[]{tm}, null);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return new Client.Default(
                ctx.getSocketFactory(), new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });
    }


    class TxTrusManagers implements TrustManager,X509TrustManager {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(X509Certificate[] certs) {
            return true;
        }

        public void checkServerTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }

        public void checkClientTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
    }


}

3.定义被调用的restful的接口的FeignClient

@FeignClient注解中指定feign client自定义配置。自定义配置中可以重写 feign.Client、feign.codec.Decoder、feign.codec.Encoder、feign.Contract 的实现方式。这些配置仅对当前的FeignClient有用

@FeignClient(name="testFeign", configuration = FeignClientHttpsNoSSLConfig.class, url = "https://192.168.103.190/api")
public interface TestFeign {
    @RequestMapping(value = "/hostPen/taskStatus",method = RequestMethod.POST)
    @ResponseBody
    public JSONObject taskStatus(@RequestBody JSONObject sss);

}

4.在controller层或者service层中调用

@RestController
public class WebPenetrationController {


    @Autowired
    private TestFeign testFeign;

   /**
    * @author     :hongyan.xu
    * @date       :Created in 2021/2/18  14:57
    * @description:任务启动
    * @modified By:
    */
    @RequestMapping(value = "taskStart",method = RequestMethod.POST,produces="application/json")
    @ResponseBody
    public String taskStart(){
        try {
           JSONObject json= testFeign.taskStatus(new JSONObject());
            System.out.println("taskStatus:"+json);
        
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }

    }
}

5.启动服务验证结果

 


版权声明:本文为redswallowxu原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。