在java工程開發(fā)過程中,如果需要向外發(fā)送網(wǎng)絡(luò)請求,但是開發(fā)過程中網(wǎng)絡(luò)不通,我們需要通過vpn的方式代理發(fā)起請求冕香。又或者需要使用ip池來進(jìn)行網(wǎng)絡(luò)爬取,也得通過ip代理來規(guī)避ip封禁后豫。
這里悉尾,給出了兩種常用的http客戶端三方類庫——OkHttp和HttpClient的代理設(shè)置
public class OkHttpUtil {
private OkHttpClient client;
private X509TrustManager x509TrustManager() {
return new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
}
private SSLSocketFactory sslSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {x509TrustManager()}, new SecureRandom());
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return null;
}
private OkHttpUtil() {
final String username = "xxx";
final String password = "yyy";
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("ipAdress", 8080));
Authenticator proxyAuthenticator = new Authenticator() {
@Override
public Request authenticate(Route route, Response response) throws IOException {
String credential = Credentials.basic(username, password);
return response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build();
}
};
client = new OkHttpClient.Builder()
.addInterceptor(new CommonInterceptor())
.retryOnConnectionFailure(false)//是否開啟緩存
.connectionPool(pool())//連接池
.connectTimeout(10L, TimeUnit.SECONDS)
.readTimeout(10L, TimeUnit.SECONDS)
.sslSocketFactory(sslSocketFactory(), x509TrustManager())
.proxy(proxy)
.proxyAuthenticator(proxyAuthenticator)
.authenticator(proxyAuthenticator)
.build();
}
// todo 使用client對象進(jìn)行執(zhí)行request請求
// client.newCall(request).execute();
}
相較于正常使用,在build的過程中挫酿,設(shè)置了proxy及proxyAuthenticator构眯。如果代理過程中ssl或tls相關(guān)的錯誤,則需要加上sslSocketFactory(sslSocketFactory(), x509TrustManager())來處理證書驗(yàn)證早龟,這里默認(rèn)的處理模式是全部放通惫霸,僅用于開發(fā)調(diào)測階段。
注:在okhttp3代理設(shè)置中葱弟,如果通過 java.net.Authenticator.setDefault的方式來設(shè)置net全局代理壹店,會報錯代理鑒權(quán)失敗。
HttpClientBuilder custom = HttpClients.custom();
//設(shè)置代理服務(wù)器
HttpHost proxy = new HttpHost("proxy.huawei.com", 8080);
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
custom.setRoutePlanner(routePlanner);
//設(shè)置代理認(rèn)證
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
new UsernamePasswordCredentials("賬號", "密碼"));
custom.setDefaultCredentialsProvider(credentialsProvider);
SSLContext sslContext = null;
try {
sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy()
{
// 信任所有
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
{
return true;
}
}).build();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
SSLConnectionSocketFactory sslf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = custom.setSSLSocketFactory(sslf).build();
// todo 使用httpClient對象進(jìn)行執(zhí)行request請求
// httpClient.execute(httpRequest).getEntity()
同理芝加,相較于正常使用硅卢,額外設(shè)置了proxy的路由及鑒權(quán):custom.setRoutePlanner(routePlanner);custom.setDefaultCredentialsProvider(credentialsProvider);
如果代理過程中ssl或tls相關(guān)的錯誤,則需要通過custom.setSSLSocketFactory來處理證書驗(yàn)證,這里默認(rèn)的處理模式是全部放通将塑,僅用于開發(fā)調(diào)測階段脉顿。
總結(jié):
通過http客戶端三方類庫,主要有三步点寥。
- 設(shè)置proxy的地址信息
- 設(shè)置proxy的鑒權(quán)信息
- 如果證書錯誤艾疟,則需要設(shè)置sslSocketFactory來處理證書驗(yàn)證。