HttpClient通过正向代理访问HTTPS接口攻略

1.问题背景

一些HTTPS接口提供方有IP白名单策略,接口调用方必须通过报备过的出口IP访问接口。对于部署在云主机上的接口调用方服务而言,这是比较不友好的。

常用的方法是在指定出口IP的服务器上部署正向代理,接口调用方服务通过这个正向代理间接访问HTTPS接口。

2.解决方案

以HttpClient4.5.3为例。

1)定义 HttpClientBuilder

HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

2)定义代理选择策略 ProxySelector

class MyProxySelector extends ProxySelector { ProxySelector defaultproxySelector = ProxySelector.getDefault(); ArrayList<Proxy> noProxy = new ArrayList<Proxy>(); ArrayList<Proxy> secureProxy = new ArrayList<Proxy>(); public MyProxySelector(String ip, int port) { // 正向代理的IP和端口 noProxy.add(Proxy.NO_PROXY); // 初始化无代理策略 secureProxy.add(new Proxy(Type.HTTP, new InetSocketAddress(ip, port))); // 初始化正向代理策略。PS:正向代理本身一般是HTTP协议的 } @Override public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { log.warn("connectFailed : " + uri); } @Override public List<Proxy> select(URI uri) { if (uri.getScheme().toLowerCase().equals("https")) { // HTTPS的请求走正向代理(此处可以自由发挥,比如限定某些域名的请求走正向代理) if (log.isDebugEnabled()) { log.debug("using secureProxy : " + uri.toString()); } return secureProxy; } if (defaultproxySelector != null) { return defaultproxySelector.select(uri); } return noProxy; } }

3)绑定代理选择策略

HttpRoutePlanner routePlanner = new SystemDefaultRoutePlanner( new MyProxySelector(proxyIp, Integer.parseInt(proxyPort))); // 定义一个路由策略,将自定义的代理选择策略传入 httpClientBuilder.setRoutePlanner(routePlanner); // 绑定路由策略 ... // 设置其他调优参数 CloseableHttpClient httpClient = httpClientBuilder.build(); // 构建 httpClient 实例

3.各种坑

1)无用代码(实测无效)

HttpHost proxy = new HttpHost(proxyIp, Integer.parseInt(proxyPort), "http"); httpClientBuilder.setProxy(proxy);

疑似这种方法没有影响路由策略,无法生效。

2)先设置系统环境变量(http_proxy、https_proxy),然后激活它们(实测无效)

httpClientBuilder.useSystemProperties();

这种方法依然没有影响路由策略,因此无法生效。

经验分享 程序员 微信小程序 职场和发展