This commit is contained in:
Looly 2023-04-17 14:42:33 +08:00
parent 12245e7c9e
commit dc26a1aca8
11 changed files with 289 additions and 104 deletions

View File

@ -179,7 +179,7 @@
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.mail</groupId> <groupId>org.eclipse.angus</groupId>
<artifactId>jakarta.mail</artifactId> <artifactId>jakarta.mail</artifactId>
<version>2.0.1</version> <version>2.0.1</version>
<scope>test</scope> <scope>test</scope>

View File

@ -1,6 +1,6 @@
package org.dromara.hutool.extra.mail; package org.dromara.hutool.extra.mail;
import com.sun.mail.util.MailSSLSocketFactory; import org.eclipse.angus.mail.util.MailSSLSocketFactory;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -12,7 +12,6 @@
package org.dromara.hutool.http; package org.dromara.hutool.http;
import org.dromara.hutool.core.codec.binary.Base64;
import org.dromara.hutool.core.net.url.UrlQueryUtil; import org.dromara.hutool.core.net.url.UrlQueryUtil;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.http.client.ClientConfig; import org.dromara.hutool.http.client.ClientConfig;
@ -216,21 +215,4 @@ public class HttpUtil {
public static SimpleServer createServer(final int port) { public static SimpleServer createServer(final int port) {
return new SimpleServer(port); return new SimpleServer(port);
} }
/**
* 构建简单的账号秘密验证信息构建后类似于
* <pre>
* Basic YWxhZGRpbjpvcGVuc2VzYW1l
* </pre>
*
* @param username 账号
* @param password 密码
* @param charset 编码如果账号或密码中有非ASCII字符适用
* @return 密码验证信息
* @since 5.4.6
*/
public static String buildBasicAuth(final String username, final String password, final Charset charset) {
final String data = username.concat(":").concat(password);
return "Basic " + Base64.encode(data, charset);
}
} }

View File

@ -1,19 +0,0 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.http.auth;
/**
*
*/
public class Credential {
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.http.auth;
import org.dromara.hutool.core.codec.binary.Base64;
import java.net.PasswordAuthentication;
import java.nio.charset.Charset;
/**
* HTTP验证工具类
*
* @author looly
* @since 6.0.0
*/
public class HttpAuthUtil {
/**
* 构建简单的账号秘密验证信息构建后类似于
* <pre>
* Basic YWxhZGRpbjpvcGVuc2VzYW1l
* </pre>
*
* @param authentication {@link PasswordAuthentication}
* @param charset 编码如果账号或密码中有非ASCII字符适用
* @return 密码验证信息
*/
public static String buildBasicAuth(final PasswordAuthentication authentication, final Charset charset) {
return buildBasicAuth(authentication.getUserName(), String.valueOf(authentication.getPassword()), charset);
}
/**
* 构建简单的账号秘密验证信息构建后类似于
* <pre>
* Basic YWxhZGRpbjpvcGVuc2VzYW1l
* </pre>
*
* @param username 账号
* @param password 密码
* @param charset 编码如果账号或密码中有非ASCII字符适用
* @return 密码验证信息
*/
public static String buildBasicAuth(final String username, final String password, final Charset charset) {
final String data = username.concat(":").concat(password);
return "Basic " + Base64.encode(data, charset);
}
}

View File

@ -13,11 +13,9 @@
package org.dromara.hutool.http.client; package org.dromara.hutool.http.client;
import org.dromara.hutool.http.HttpGlobalConfig; import org.dromara.hutool.http.HttpGlobalConfig;
import org.dromara.hutool.http.proxy.HttpProxy;
import org.dromara.hutool.http.ssl.SSLInfo; import org.dromara.hutool.http.ssl.SSLInfo;
import java.net.InetSocketAddress;
import java.net.Proxy;
/** /**
* Http客户端配置 * Http客户端配置
* *
@ -53,7 +51,7 @@ public class ClientConfig {
/** /**
* 代理 * 代理
*/ */
private Proxy proxy; private HttpProxy proxy;
/** /**
* 构造 * 构造
@ -169,7 +167,7 @@ public class ClientConfig {
* *
* @return 代理 * @return 代理
*/ */
public Proxy getProxy() { public HttpProxy getProxy() {
return proxy; return proxy;
} }
@ -181,18 +179,16 @@ public class ClientConfig {
* @return this * @return this
*/ */
public ClientConfig setHttpProxy(final String host, final int port) { public ClientConfig setHttpProxy(final String host, final int port) {
final Proxy proxy = new Proxy(Proxy.Type.HTTP, return setProxy(new HttpProxy(host, port));
new InetSocketAddress(host, port));
return setProxy(proxy);
} }
/** /**
* 设置代理 * 设置代理
* *
* @param proxy 代理 {@link Proxy} * @param proxy 代理 {@link HttpProxy}
* @return this * @return this
*/ */
public ClientConfig setProxy(final Proxy proxy) { public ClientConfig setProxy(final HttpProxy proxy) {
this.proxy = proxy; this.proxy = proxy;
return this; return this;
} }

View File

@ -12,6 +12,19 @@
package org.dromara.hutool.http.client.engine.httpclient4; package org.dromara.hutool.http.client.engine.httpclient4;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
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.BasicCredentialsProvider;
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 org.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.net.url.UrlBuilder; import org.dromara.hutool.core.net.url.UrlBuilder;
@ -23,18 +36,11 @@ import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.Response; import org.dromara.hutool.http.client.Response;
import org.dromara.hutool.http.client.body.HttpBody; import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.meta.HeaderName; import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.proxy.HttpProxy;
import org.dromara.hutool.http.ssl.SSLInfo; import org.dromara.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.io.IOException;
import java.net.PasswordAuthentication;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -115,6 +121,9 @@ public class HttpClient4Engine implements ClientEngine {
// 设置默认头信息 // 设置默认头信息
clientBuilder.setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers())); clientBuilder.setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers()));
// 设置代理
setProxy(clientBuilder, config);
this.engine = clientBuilder.build(); this.engine = clientBuilder.build();
} }
@ -200,4 +209,31 @@ public class HttpClient4Engine implements ClientEngine {
return requestConfigBuilder.build(); return requestConfigBuilder.build();
} }
/**
* 设置代理信息
*
* @param clientBuilder {@link org.apache.hc.client5.http.impl.classic.HttpClientBuilder}
* @param config 配置
*/
private static void setProxy(final HttpClientBuilder clientBuilder, final ClientConfig config) {
if (null == config) {
return;
}
final HttpProxy proxy = config.getProxy();
if (null != proxy) {
final HttpHost httpHost = new HttpHost(proxy.getHost(), proxy.getPort());
clientBuilder.setProxy(httpHost);
final PasswordAuthentication auth = proxy.getAuth();
if (null != auth) {
// 代理验证
final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(httpHost),
new UsernamePasswordCredentials(auth.getUserName(), String.valueOf(auth.getPassword())));
clientBuilder.setDefaultCredentialsProvider(credsProvider);
}
}
}
} }

View File

@ -12,6 +12,23 @@
package org.dromara.hutool.http.client.engine.httpclient5; package org.dromara.hutool.http.client.engine.httpclient5;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
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.auth.BasicCredentialsProvider;
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;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.message.BasicHeader;
import org.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.net.url.UrlBuilder; import org.dromara.hutool.core.net.url.UrlBuilder;
@ -23,22 +40,11 @@ import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.Response; import org.dromara.hutool.http.client.Response;
import org.dromara.hutool.http.client.body.HttpBody; import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.meta.HeaderName; import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.proxy.HttpProxy;
import org.dromara.hutool.http.ssl.SSLInfo; import org.dromara.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;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.message.BasicHeader;
import java.io.IOException; import java.io.IOException;
import java.net.PasswordAuthentication;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -116,7 +122,8 @@ public class HttpClient5Engine implements ClientEngine {
// 设置默认头信息 // 设置默认头信息
clientBuilder.setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers())); clientBuilder.setDefaultHeaders(toHeaderList(GlobalHeaders.INSTANCE.headers()));
// TODO 设置代理 // 设置代理
setProxy(clientBuilder, config);
this.engine = clientBuilder.build(); this.engine = clientBuilder.build();
} }
@ -211,4 +218,31 @@ public class HttpClient5Engine implements ClientEngine {
return requestConfigBuilder.build(); return requestConfigBuilder.build();
} }
/**
* 设置代理信息
*
* @param clientBuilder {@link HttpClientBuilder}
* @param config 配置
*/
private static void setProxy(final HttpClientBuilder clientBuilder, final ClientConfig config) {
if (null == config) {
return;
}
final HttpProxy proxy = config.getProxy();
if (null != proxy) {
final HttpHost httpHost = new HttpHost(proxy.getHost(), proxy.getPort());
clientBuilder.setProxy(httpHost);
final PasswordAuthentication auth = proxy.getAuth();
if (null != auth) {
// 代理验证
final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(httpHost),
new UsernamePasswordCredentials(auth.getUserName(), auth.getPassword()));
clientBuilder.setDefaultCredentialsProvider(credsProvider);
}
}
}
} }

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.http.client.engine.okhttp;
import okhttp3.*;
import org.dromara.hutool.http.meta.HeaderName;
import java.net.PasswordAuthentication;
/**
* 账号密码形式的代理验证<br>
* 生成类似
* <pre>
* Proxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
* </pre>
*
* @author looly
* @since 6.0.0
*/
public class BasicProxyAuthenticator implements Authenticator {
private final PasswordAuthentication auth;
/**
* 构造
*
* @param passwordAuthentication 账号密码对
*/
public BasicProxyAuthenticator(final PasswordAuthentication passwordAuthentication) {
auth = passwordAuthentication;
}
@Override
public Request authenticate(final Route route, final Response response) {
final String credential = Credentials.basic(
auth.getUserName(),
String.valueOf(auth.getPassword()));
return response.request().newBuilder()
.addHeader(HeaderName.PROXY_AUTHORIZATION.getValue(), credential)
.build();
}
}

View File

@ -12,17 +12,18 @@
package org.dromara.hutool.http.client.engine.okhttp; package org.dromara.hutool.http.client.engine.okhttp;
import okhttp3.OkHttpClient;
import okhttp3.internal.http.HttpMethod;
import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.http.client.ClientConfig; import org.dromara.hutool.http.client.ClientConfig;
import org.dromara.hutool.http.client.ClientEngine; import org.dromara.hutool.http.client.ClientEngine;
import org.dromara.hutool.http.client.Request; import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.Response; import org.dromara.hutool.http.client.Response;
import org.dromara.hutool.http.proxy.HttpProxy;
import org.dromara.hutool.http.ssl.SSLInfo; import org.dromara.hutool.http.ssl.SSLInfo;
import okhttp3.OkHttpClient;
import okhttp3.internal.http.HttpMethod;
import java.io.IOException; import java.io.IOException;
import java.net.Proxy; import java.net.PasswordAuthentication;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -107,10 +108,7 @@ public class OkHttpEngine implements ClientEngine {
} }
// 设置代理 // 设置代理
final Proxy proxy = config.getProxy(); setProxy(builder, config);
if (null != proxy) {
builder.proxy(proxy);
}
} }
this.client = builder.build(); this.client = builder.build();
@ -135,4 +133,21 @@ public class OkHttpEngine implements ClientEngine {
return builder.build(); return builder.build();
} }
/**
* 设置代理信息
*
* @param builder 客户端构建器
* @param config 配置
*/
private static void setProxy(final OkHttpClient.Builder builder, final ClientConfig config) {
final HttpProxy proxy = config.getProxy();
if (null != proxy) {
builder.proxy(proxy);
final PasswordAuthentication auth = proxy.getAuth();
if (null != auth) {
builder.proxyAuthenticator(new BasicProxyAuthenticator(auth));
}
}
}
} }

View File

@ -13,6 +13,7 @@
package org.dromara.hutool.http.proxy; package org.dromara.hutool.http.proxy;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy; import java.net.Proxy;
/** /**
@ -25,6 +26,7 @@ public class HttpProxy extends Proxy {
private final String host; private final String host;
private final int port; private final int port;
private PasswordAuthentication auth;
/** /**
* 构造 * 构造
@ -56,4 +58,34 @@ public class HttpProxy extends Proxy {
return port; return port;
} }
/**
* 设置代理验证信息
*
* @param user 用户名
* @param pass 密码
* @return this
*/
public HttpProxy setAuth(final String user, final char[] pass) {
return setAuth(new PasswordAuthentication(user, pass));
}
/**
* 设置代理验证信息
*
* @param auth {@link PasswordAuthentication}
* @return this
*/
public HttpProxy setAuth(final PasswordAuthentication auth) {
this.auth = auth;
return this;
}
/**
* 获取代理验证信息
*
* @return {@link PasswordAuthentication}
*/
public PasswordAuthentication getAuth() {
return this.auth;
}
} }