mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-24 18:04:54 +08:00
fix code
This commit is contained in:
parent
fb7e88515a
commit
d80747f9d5
@ -13,6 +13,7 @@ import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
|
||||
/**
|
||||
* {@link SSLContext}构建器,可以自定义:<br>
|
||||
* <ul>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package cn.hutool.http.ssl;
|
||||
package cn.hutool.core.net.ssl;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLSession;
|
||||
@ -10,6 +10,11 @@ import javax.net.ssl.SSLSession;
|
||||
*/
|
||||
public class TrustAnyHostnameVerifier implements HostnameVerifier {
|
||||
|
||||
/**
|
||||
* 单例对象
|
||||
*/
|
||||
public static TrustAnyHostnameVerifier INSTANCE = new TrustAnyHostnameVerifier();
|
||||
|
||||
@Override
|
||||
public boolean verify(final String hostname, final SSLSession session) {
|
||||
return true;// 直接返回true
|
@ -1,12 +1,8 @@
|
||||
package cn.hutool.http.client;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.net.ssl.SSLUtil;
|
||||
import cn.hutool.http.HttpGlobalConfig;
|
||||
import cn.hutool.http.ssl.TrustAnySSLInfo;
|
||||
import cn.hutool.http.ssl.SSLInfo;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
|
||||
@ -35,14 +31,7 @@ public class ClientConfig {
|
||||
*/
|
||||
private int readTimeout;
|
||||
|
||||
/**
|
||||
* HostnameVerifier,用于HTTPS安全连接
|
||||
*/
|
||||
private HostnameVerifier hostnameVerifier;
|
||||
/**
|
||||
* SSLSocketFactory,用于HTTPS安全连接
|
||||
*/
|
||||
private SSLSocketFactory socketFactory;
|
||||
private SSLInfo sslInfo;
|
||||
/**
|
||||
* 是否禁用缓存
|
||||
*/
|
||||
@ -58,8 +47,7 @@ public class ClientConfig {
|
||||
public ClientConfig() {
|
||||
connectionTimeout = HttpGlobalConfig.getTimeout();
|
||||
readTimeout = HttpGlobalConfig.getTimeout();
|
||||
hostnameVerifier = TrustAnySSLInfo.TRUST_ANY_HOSTNAME_VERIFIER;
|
||||
socketFactory = TrustAnySSLInfo.DEFAULT_SSF;
|
||||
sslInfo = SSLInfo.TRUST_ANY;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,34 +111,12 @@ public class ClientConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取域名验证器
|
||||
* 获取SSLInfo
|
||||
*
|
||||
* @return 域名验证器
|
||||
* @return SSLInfo
|
||||
*/
|
||||
public HostnameVerifier getHostnameVerifier() {
|
||||
return hostnameVerifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置域名验证器<br>
|
||||
* 只针对HTTPS请求,如果不设置,不做验证,所有域名被信任
|
||||
*
|
||||
* @param hostnameVerifier HostnameVerifier
|
||||
* @return this
|
||||
*/
|
||||
public ClientConfig setHostnameVerifier(final HostnameVerifier hostnameVerifier) {
|
||||
// 验证域
|
||||
this.hostnameVerifier = hostnameVerifier;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取SSLSocketFactory
|
||||
*
|
||||
* @return SSLSocketFactory
|
||||
*/
|
||||
public SSLSocketFactory getSocketFactory() {
|
||||
return socketFactory;
|
||||
public SSLInfo getSslInfo() {
|
||||
return this.sslInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -158,33 +124,11 @@ public class ClientConfig {
|
||||
* 只针对HTTPS请求,如果不设置,使用默认的SSLSocketFactory<br>
|
||||
* 默认SSLSocketFactory为:SSLSocketFactoryBuilder.create().build();
|
||||
*
|
||||
* @param ssf SSLScketFactory
|
||||
* @param sslInfo SSLInfo
|
||||
* @return this
|
||||
*/
|
||||
public ClientConfig setSocketFactory(final SSLSocketFactory ssf) {
|
||||
this.socketFactory = ssf;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置HTTPS安全连接协议,只针对HTTPS请求,可以使用的协议包括:<br>
|
||||
* 此方法调用后{@link #setSocketFactory(SSLSocketFactory)} 将被覆盖。
|
||||
*
|
||||
* <pre>
|
||||
* 1. TLSv1.2
|
||||
* 2. TLSv1.1
|
||||
* 3. SSLv3
|
||||
* ...
|
||||
* </pre>
|
||||
*
|
||||
* @param protocol 协议
|
||||
* @return this
|
||||
* @see SSLUtil#createTrustAnySSLContext(String)
|
||||
* @see #setSocketFactory(SSLSocketFactory)
|
||||
*/
|
||||
public ClientConfig setSSLProtocol(final String protocol) {
|
||||
Assert.notBlank(protocol, "protocol must be not blank!");
|
||||
setSocketFactory(SSLUtil.createTrustAnySSLContext(protocol).getSocketFactory());
|
||||
public ClientConfig setSSLInfo(final SSLInfo sslInfo) {
|
||||
this.sslInfo = sslInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -10,19 +10,26 @@ import cn.hutool.http.client.ClientEngine;
|
||||
import cn.hutool.http.client.Request;
|
||||
import cn.hutool.http.client.Response;
|
||||
import cn.hutool.http.client.body.HttpBody;
|
||||
import cn.hutool.http.ssl.SSLInfo;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Apache HttpClient5的HTTP请求引擎
|
||||
@ -38,7 +45,8 @@ public class HttpClient4Engine implements ClientEngine {
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public HttpClient4Engine() {}
|
||||
public HttpClient4Engine() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpClient4Engine setConfig(final ClientConfig config) {
|
||||
@ -77,33 +85,27 @@ public class HttpClient4Engine implements ClientEngine {
|
||||
/**
|
||||
* 初始化引擎
|
||||
*/
|
||||
private void initEngine(){
|
||||
if(null != this.engine){
|
||||
private void initEngine() {
|
||||
if (null != this.engine) {
|
||||
return;
|
||||
}
|
||||
|
||||
RequestConfig requestConfig = null;
|
||||
if(null != this.config){
|
||||
final RequestConfig.Builder builder = RequestConfig.custom();
|
||||
|
||||
final int connectionTimeout = this.config.getConnectionTimeout();
|
||||
if(connectionTimeout > 0){
|
||||
builder.setConnectTimeout(connectionTimeout);
|
||||
builder.setConnectionRequestTimeout(connectionTimeout);
|
||||
}
|
||||
final int readTimeout = this.config.getReadTimeout();
|
||||
if(readTimeout > 0){
|
||||
builder.setSocketTimeout(readTimeout);
|
||||
final HttpClientBuilder clientBuilder = HttpClients.custom();
|
||||
final ClientConfig config = this.config;
|
||||
if (null != config) {
|
||||
// SSL配置
|
||||
final SSLInfo sslInfo = config.getSslInfo();
|
||||
if (null != sslInfo) {
|
||||
clientBuilder.setSSLSocketFactory(buildSocketFactory(sslInfo));
|
||||
}
|
||||
|
||||
requestConfig = builder.build();
|
||||
clientBuilder.setDefaultRequestConfig(buildRequestConfig(config));
|
||||
}
|
||||
|
||||
this.engine = HttpClients.custom()
|
||||
// 设置默认头信息
|
||||
.setDefaultRequestConfig(requestConfig)
|
||||
.setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers()))
|
||||
.build();
|
||||
// 设置默认头信息
|
||||
clientBuilder.setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers()));
|
||||
|
||||
this.engine = clientBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,4 +153,41 @@ public class HttpClient4Engine implements ClientEngine {
|
||||
headersMap.forEach((k, v1) -> v1.forEach((v2) -> result.add(new BasicHeader(k, v2))));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持SSL
|
||||
*
|
||||
* @return SSLConnectionSocketFactory
|
||||
*/
|
||||
private static SSLConnectionSocketFactory buildSocketFactory(final SSLInfo sslInfo) {
|
||||
return new SSLConnectionSocketFactory(
|
||||
sslInfo.getSslContext(),
|
||||
sslInfo.getProtocols(),
|
||||
null,
|
||||
sslInfo.getHostnameVerifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建请求配置,包括连接请求超时和响应(读取)超时
|
||||
*
|
||||
* @param config {@link ClientConfig}
|
||||
* @return {@link RequestConfig}
|
||||
*/
|
||||
private static RequestConfig buildRequestConfig(final ClientConfig config) {
|
||||
// 请求配置
|
||||
final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
|
||||
|
||||
// 连接超时
|
||||
final int connectionTimeout = config.getConnectionTimeout();
|
||||
if (connectionTimeout > 0) {
|
||||
requestConfigBuilder.setConnectTimeout(connectionTimeout);
|
||||
requestConfigBuilder.setConnectionRequestTimeout(connectionTimeout);
|
||||
}
|
||||
final int readTimeout = config.getReadTimeout();
|
||||
if (readTimeout > 0) {
|
||||
requestConfigBuilder.setSocketTimeout(readTimeout);
|
||||
}
|
||||
|
||||
return requestConfigBuilder.build();
|
||||
}
|
||||
}
|
||||
|
@ -11,12 +11,14 @@ import cn.hutool.http.client.ClientEngine;
|
||||
import cn.hutool.http.client.Request;
|
||||
import cn.hutool.http.client.Response;
|
||||
import cn.hutool.http.client.body.HttpBody;
|
||||
import cn.hutool.http.ssl.SSLInfo;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
|
||||
import org.apache.hc.client5.http.config.ConnectionConfig;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
|
||||
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder;
|
||||
import org.apache.hc.core5.http.ClassicHttpRequest;
|
||||
@ -45,7 +47,8 @@ public class HttpClient5Engine implements ClientEngine {
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public HttpClient5Engine() {}
|
||||
public HttpClient5Engine() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpClient5Engine setConfig(final ClientConfig config) {
|
||||
@ -84,47 +87,25 @@ public class HttpClient5Engine implements ClientEngine {
|
||||
/**
|
||||
* 初始化引擎
|
||||
*/
|
||||
private void initEngine(){
|
||||
if(null != this.engine){
|
||||
private void initEngine() {
|
||||
if (null != this.engine) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 连接配置
|
||||
final PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder.create()
|
||||
.setSSLSocketFactory(SSLConnectionSocketFactoryBuilder.create()
|
||||
.setSslContext(SSLUtil.createTrustAnySSLContext()).build());
|
||||
final HttpClientBuilder clientBuilder = HttpClients.custom();
|
||||
|
||||
// 请求配置
|
||||
RequestConfig requestConfig = null;
|
||||
|
||||
if(null != this.config){
|
||||
final int connectionTimeout = this.config.getConnectionTimeout();
|
||||
if(connectionTimeout > 0){
|
||||
connectionManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom()
|
||||
.setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build());
|
||||
}
|
||||
final RequestConfig.Builder builder = RequestConfig.custom();
|
||||
|
||||
if(connectionTimeout > 0){
|
||||
builder.setConnectionRequestTimeout(connectionTimeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
final int readTimeout = this.config.getReadTimeout();
|
||||
if(readTimeout > 0){
|
||||
builder.setResponseTimeout(readTimeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
requestConfig = builder.build();
|
||||
final ClientConfig config = this.config;
|
||||
if (null != config) {
|
||||
clientBuilder.setConnectionManager(buildConnectionManager(config));
|
||||
clientBuilder.setDefaultRequestConfig(buildRequestConfig(config));
|
||||
}
|
||||
|
||||
final HttpClientBuilder builder = HttpClients.custom()
|
||||
.setConnectionManager(connectionManagerBuilder.build())
|
||||
.setDefaultRequestConfig(requestConfig)
|
||||
// 设置默认头信息
|
||||
.setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers()));
|
||||
// 设置默认头信息
|
||||
clientBuilder.setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers()));
|
||||
|
||||
// TODO 设置代理
|
||||
|
||||
this.engine = builder.build();
|
||||
this.engine = clientBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,4 +148,54 @@ public class HttpClient5Engine implements ClientEngine {
|
||||
headersMap.forEach((k, v1) -> v1.forEach((v2) -> result.add(new BasicHeader(k, v2))));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建连接管理器,包括SSL配置和连接超时配置
|
||||
*
|
||||
* @param config {@link ClientConfig}
|
||||
* @return {@link PoolingHttpClientConnectionManager}
|
||||
*/
|
||||
private static PoolingHttpClientConnectionManager buildConnectionManager(final ClientConfig config) {
|
||||
final PoolingHttpClientConnectionManagerBuilder connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder.create();
|
||||
// SSL配置
|
||||
final SSLInfo sslInfo = config.getSslInfo();
|
||||
if (null != sslInfo) {
|
||||
connectionManagerBuilder.setSSLSocketFactory(SSLConnectionSocketFactoryBuilder.create()
|
||||
.setTlsVersions(sslInfo.getProtocols())
|
||||
.setSslContext(sslInfo.getSslContext())
|
||||
.setHostnameVerifier(sslInfo.getHostnameVerifier())
|
||||
.build());
|
||||
}
|
||||
// 连接超时配置
|
||||
final int connectionTimeout = config.getConnectionTimeout();
|
||||
if (connectionTimeout > 0) {
|
||||
connectionManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom()
|
||||
.setSocketTimeout(connectionTimeout, TimeUnit.MILLISECONDS)
|
||||
.setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build());
|
||||
}
|
||||
|
||||
return connectionManagerBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建请求配置,包括连接请求超时和响应(读取)超时
|
||||
*
|
||||
* @param config {@link ClientConfig}
|
||||
* @return {@link RequestConfig}
|
||||
*/
|
||||
private static RequestConfig buildRequestConfig(final ClientConfig config) {
|
||||
final int connectionTimeout = config.getConnectionTimeout();
|
||||
|
||||
// 请求配置
|
||||
final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
|
||||
if (connectionTimeout > 0) {
|
||||
requestConfigBuilder.setConnectionRequestTimeout(connectionTimeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
final int readTimeout = config.getReadTimeout();
|
||||
if (readTimeout > 0) {
|
||||
requestConfigBuilder.setResponseTimeout(readTimeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
return requestConfigBuilder.build();
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,9 @@ import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.http.HttpException;
|
||||
import cn.hutool.http.client.HeaderOperation;
|
||||
import cn.hutool.http.meta.Method;
|
||||
import cn.hutool.http.ssl.TrustAnySSLInfo;
|
||||
import cn.hutool.http.ssl.SSLInfo;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@ -196,23 +194,23 @@ public class HttpConnection implements HeaderOperation<HttpConnection> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置https请求参数<br>
|
||||
* 设置https中SSL相关请求参数<br>
|
||||
* 有些时候htts请求会出现com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImpl的实现,此为sun内部api,按照普通http请求处理
|
||||
*
|
||||
* @param hostnameVerifier 域名验证器,非https传入null
|
||||
* @param ssf SSLSocketFactory,非https传入null
|
||||
* @param sslInfo {@link SSLInfo}
|
||||
* @return this
|
||||
* @throws HttpException KeyManagementException和NoSuchAlgorithmException异常包装
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public HttpConnection setHttpsInfo(final HostnameVerifier hostnameVerifier, final SSLSocketFactory ssf) throws HttpException {
|
||||
public HttpConnection setSSLInfo(final SSLInfo sslInfo) throws HttpException {
|
||||
final HttpURLConnection conn = this.conn;
|
||||
|
||||
if (conn instanceof HttpsURLConnection) {
|
||||
// Https请求
|
||||
final HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
|
||||
// 验证域
|
||||
httpsConn.setHostnameVerifier(ObjUtil.defaultIfNull(hostnameVerifier, TrustAnySSLInfo.TRUST_ANY_HOSTNAME_VERIFIER));
|
||||
httpsConn.setSSLSocketFactory(ObjUtil.defaultIfNull(ssf, TrustAnySSLInfo.DEFAULT_SSF));
|
||||
httpsConn.setHostnameVerifier(ObjUtil.defaultIfNull(sslInfo.getHostnameVerifier(), SSLInfo.TRUST_ANY.getHostnameVerifier()));
|
||||
httpsConn.setSSLSocketFactory(ObjUtil.defaultIfNull(sslInfo.getSocketFactory(), SSLInfo.TRUST_ANY.getSocketFactory()));
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -129,7 +129,7 @@ public class JdkClientEngine implements ClientEngine {
|
||||
.setConnectTimeout(config.getConnectionTimeout())
|
||||
.setReadTimeout(config.getReadTimeout())
|
||||
.setMethod(message.method())//
|
||||
.setHttpsInfo(config.getHostnameVerifier(), config.getSocketFactory())
|
||||
.setSSLInfo(config.getSslInfo())
|
||||
// 关闭JDK自动转发,采用手动转发方式
|
||||
.setInstanceFollowRedirects(false)
|
||||
.setChunkedStreamingMode(message.isChunked() ? 4096 : -1)
|
||||
|
@ -6,6 +6,7 @@ import cn.hutool.http.client.ClientConfig;
|
||||
import cn.hutool.http.client.ClientEngine;
|
||||
import cn.hutool.http.client.Request;
|
||||
import cn.hutool.http.client.Response;
|
||||
import cn.hutool.http.ssl.SSLInfo;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.internal.http.HttpMethod;
|
||||
|
||||
@ -71,15 +72,34 @@ public class OkHttpEngine implements ClientEngine {
|
||||
return;
|
||||
}
|
||||
|
||||
final ClientConfig config = ObjUtil.defaultIfNull(this.config, ClientConfig::of);
|
||||
final OkHttpClient.Builder builder = new OkHttpClient.Builder()
|
||||
.connectTimeout(config.getConnectionTimeout(), TimeUnit.MILLISECONDS)
|
||||
.readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS);
|
||||
final OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||
|
||||
// 设置代理
|
||||
final Proxy proxy = config.getProxy();
|
||||
if(null != proxy){
|
||||
builder.proxy(proxy);
|
||||
final ClientConfig config = this.config;
|
||||
if (null != config) {
|
||||
// 连接超时
|
||||
final int connectionTimeout = config.getConnectionTimeout();
|
||||
if (connectionTimeout > 0) {
|
||||
builder.connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
// 读写超时
|
||||
final int readTimeout = config.getReadTimeout();
|
||||
if (readTimeout > 0) {
|
||||
// 读写共用读取超时
|
||||
builder.readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS)
|
||||
.writeTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
// SSL
|
||||
final SSLInfo sslInfo = config.getSslInfo();
|
||||
if(null != sslInfo){
|
||||
builder.sslSocketFactory(sslInfo.getSocketFactory(), sslInfo.getTrustManager());
|
||||
}
|
||||
|
||||
// 设置代理
|
||||
final Proxy proxy = config.getProxy();
|
||||
if (null != proxy) {
|
||||
builder.proxy(proxy);
|
||||
}
|
||||
}
|
||||
|
||||
this.client = builder.build();
|
||||
|
@ -1,30 +0,0 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.net.ssl.SSLProtocols;
|
||||
|
||||
/**
|
||||
* 兼容android低版本SSL连接<br>
|
||||
* 在测试HttpUrlConnection的时候,发现一部分手机无法连接[GithubPage]
|
||||
*
|
||||
* <p>
|
||||
* 最后发现原来是某些SSL协议没有开启
|
||||
*
|
||||
* @author MikaGuraNTK
|
||||
*/
|
||||
public class AndroidSupportSSLFactory extends CustomProtocolsSSLFactory {
|
||||
|
||||
// Android低版本不重置的话某些SSL访问就会失败
|
||||
private static final String[] protocols = {
|
||||
SSLProtocols.SSLv3, SSLProtocols.TLSv1, SSLProtocols.TLSv11, SSLProtocols.TLSv12};
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public AndroidSupportSSLFactory() throws IORuntimeException {
|
||||
super(protocols);
|
||||
}
|
||||
|
||||
}
|
@ -17,68 +17,68 @@ import java.net.Socket;
|
||||
*/
|
||||
public class CustomProtocolsSSLFactory extends SSLSocketFactory {
|
||||
|
||||
private final SSLSocketFactory raw;
|
||||
private final String[] protocols;
|
||||
private final SSLSocketFactory base;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param factory {@link SSLSocketFactory}
|
||||
* @param protocols 支持协议列表
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public CustomProtocolsSSLFactory(final String... protocols) throws IORuntimeException {
|
||||
public CustomProtocolsSSLFactory(final SSLSocketFactory factory, final String... protocols) {
|
||||
this.raw = factory;
|
||||
this.protocols = protocols;
|
||||
this.base = SSLUtil.createTrustAnySSLContext(null).getSocketFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return base.getDefaultCipherSuites();
|
||||
return raw.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return base.getSupportedCipherSuites();
|
||||
return raw.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket() throws IOException {
|
||||
final SSLSocket sslSocket = (SSLSocket) base.createSocket();
|
||||
final SSLSocket sslSocket = (SSLSocket) raw.createSocket();
|
||||
resetProtocols(sslSocket);
|
||||
return sslSocket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLSocket createSocket(final Socket s, final String host, final int port, final boolean autoClose) throws IOException {
|
||||
final SSLSocket socket = (SSLSocket) base.createSocket(s, host, port, autoClose);
|
||||
final SSLSocket socket = (SSLSocket) raw.createSocket(s, host, port, autoClose);
|
||||
resetProtocols(socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(final String host, final int port) throws IOException {
|
||||
final SSLSocket socket = (SSLSocket) base.createSocket(host, port);
|
||||
final SSLSocket socket = (SSLSocket) raw.createSocket(host, port);
|
||||
resetProtocols(socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(final String host, final int port, final InetAddress localHost, final int localPort) throws IOException {
|
||||
final SSLSocket socket = (SSLSocket) base.createSocket(host, port, localHost, localPort);
|
||||
final SSLSocket socket = (SSLSocket) raw.createSocket(host, port, localHost, localPort);
|
||||
resetProtocols(socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(final InetAddress host, final int port) throws IOException {
|
||||
final SSLSocket socket = (SSLSocket) base.createSocket(host, port);
|
||||
final SSLSocket socket = (SSLSocket) raw.createSocket(host, port);
|
||||
resetProtocols(socket);
|
||||
return socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(final InetAddress address, final int port, final InetAddress localAddress, final int localPort) throws IOException {
|
||||
final SSLSocket socket = (SSLSocket) base.createSocket(address, port, localAddress, localPort);
|
||||
final SSLSocket socket = (SSLSocket) raw.createSocket(address, port, localAddress, localPort);
|
||||
resetProtocols(socket);
|
||||
return socket;
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
/**
|
||||
* 默认的SSLSocketFactory
|
||||
*
|
||||
* @author Looly
|
||||
* @since 5.1.2
|
||||
*/
|
||||
public class DefaultSSLFactory extends CustomProtocolsSSLFactory {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public DefaultSSLFactory() {}
|
||||
}
|
169
hutool-http/src/main/java/cn/hutool/http/ssl/SSLInfo.java
Executable file
169
hutool-http/src/main/java/cn/hutool/http/ssl/SSLInfo.java
Executable file
@ -0,0 +1,169 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import cn.hutool.core.net.ssl.SSLProtocols;
|
||||
import cn.hutool.core.net.ssl.SSLUtil;
|
||||
import cn.hutool.core.net.ssl.TrustAnyHostnameVerifier;
|
||||
import cn.hutool.core.net.ssl.TrustAnyTrustManager;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
/**
|
||||
* HTTP请求中SSL相关信息,包括:
|
||||
* <ul>
|
||||
* <li>{@link HostnameVerifier}</li>
|
||||
* <li>{@link SSLContext}</li>
|
||||
* <li>{@link X509TrustManager}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class SSLInfo {
|
||||
|
||||
/**
|
||||
* 默认{@code SSLInfo},全部为{@code null},使用客户端引擎默认配置
|
||||
*/
|
||||
public static final SSLInfo DEFAULT = SSLInfo.of();
|
||||
|
||||
/**
|
||||
* 信任所有的{@code SSLInfo}
|
||||
*/
|
||||
public static final SSLInfo TRUST_ANY = SSLInfo.of()
|
||||
.setHostnameVerifier(TrustAnyHostnameVerifier.INSTANCE)
|
||||
.setSslContext(SSLUtil.createTrustAnySSLContext())
|
||||
.setTrustManager(TrustAnyTrustManager.INSTANCE);
|
||||
|
||||
/**
|
||||
* 构建{@code SSLInfo}
|
||||
*
|
||||
* @return {@code SSLInfo}
|
||||
*/
|
||||
public static SSLInfo of() {
|
||||
return new SSLInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持的协议类型
|
||||
*/
|
||||
private String[] protocols;
|
||||
/**
|
||||
* HostnameVerifier,用于HTTPS安全连接
|
||||
*/
|
||||
private HostnameVerifier hostnameVerifier;
|
||||
/**
|
||||
* SSLContext,用于HTTPS安全连接
|
||||
*/
|
||||
private SSLContext sslContext;
|
||||
/**
|
||||
* 信任管理器
|
||||
*/
|
||||
private X509TrustManager trustManager;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public SSLInfo() {
|
||||
if (StrUtil.equalsIgnoreCase("dalvik", System.getProperty("java.vm.name"))) {
|
||||
//兼容android低版本SSL连接
|
||||
this.protocols = new String[]{
|
||||
SSLProtocols.SSLv3,
|
||||
SSLProtocols.TLSv1,
|
||||
SSLProtocols.TLSv11,
|
||||
SSLProtocols.TLSv12};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有支持的协议
|
||||
*
|
||||
* @return 协议列表
|
||||
*/
|
||||
public String[] getProtocols() {
|
||||
return protocols;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置协议列表
|
||||
*
|
||||
* @param protocols 协议列表
|
||||
* @return this
|
||||
*/
|
||||
public SSLInfo setProtocols(final String... protocols) {
|
||||
this.protocols = protocols;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@link HostnameVerifier}
|
||||
*
|
||||
* @return {@link HostnameVerifier}
|
||||
*/
|
||||
public HostnameVerifier getHostnameVerifier() {
|
||||
return hostnameVerifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置{@link HostnameVerifier},信任所有则使用{@link cn.hutool.core.net.ssl.TrustAnyHostnameVerifier}
|
||||
*
|
||||
* @param hostnameVerifier {@link HostnameVerifier}
|
||||
* @return this
|
||||
*/
|
||||
public SSLInfo setHostnameVerifier(final HostnameVerifier hostnameVerifier) {
|
||||
this.hostnameVerifier = hostnameVerifier;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@link SSLContext}
|
||||
*
|
||||
* @return {@link SSLContext}
|
||||
*/
|
||||
public SSLContext getSslContext() {
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置{@link SSLContext},可以使用{@link cn.hutool.core.net.ssl.SSLContextBuilder}构建
|
||||
*
|
||||
* @param sslContext {@link SSLContext}
|
||||
* @return this
|
||||
*/
|
||||
public SSLInfo setSslContext(final SSLContext sslContext) {
|
||||
this.sslContext = sslContext;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@link X509TrustManager}
|
||||
*
|
||||
* @return {@link X509TrustManager}
|
||||
*/
|
||||
public X509TrustManager getTrustManager() {
|
||||
return trustManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置{@link X509TrustManager},新人所有则使用{@link cn.hutool.core.net.ssl.TrustAnyTrustManager}
|
||||
*
|
||||
* @param trustManager {@link X509TrustManager}
|
||||
* @return this
|
||||
*/
|
||||
public SSLInfo setTrustManager(final X509TrustManager trustManager) {
|
||||
this.trustManager = trustManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@link SSLSocketFactory}
|
||||
*
|
||||
* @return {@link SSLSocketFactory}
|
||||
*/
|
||||
public SSLSocketFactory getSocketFactory() {
|
||||
final SSLSocketFactory factory = this.sslContext.getSocketFactory();
|
||||
return new CustomProtocolsSSLFactory(factory, this.protocols);
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
/**
|
||||
* 新任所有SSL配置
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
public class TrustAnySSLInfo {
|
||||
/**
|
||||
* 默认信任全部的域名校验器
|
||||
*/
|
||||
public static final TrustAnyHostnameVerifier TRUST_ANY_HOSTNAME_VERIFIER;
|
||||
/**
|
||||
* 默认的SSLSocketFactory,区分安卓
|
||||
*/
|
||||
public static final SSLSocketFactory DEFAULT_SSF;
|
||||
|
||||
static {
|
||||
TRUST_ANY_HOSTNAME_VERIFIER = new TrustAnyHostnameVerifier();
|
||||
if (StrUtil.equalsIgnoreCase("dalvik", System.getProperty("java.vm.name"))) {
|
||||
// 兼容android低版本SSL连接
|
||||
DEFAULT_SSF = new AndroidSupportSSLFactory();
|
||||
} else {
|
||||
DEFAULT_SSF = new DefaultSSLFactory();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user