使用URLConnection进行访问

时间:2021-11-20 21:49:26

用URLConnection写的一个http和https请求的工具类。

支持双向验证。如果对方要验证我们发送的证书,发送前先setKeyStore();如果我们要验证对方发送的证书,发送前先setTrustStore()。

package test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
import org.apache.log4j.Logger;
import sun.misc.BASE64Encoder; public class HttpUtil {
private static Logger logger = Logger.getLogger(HttpUtil.class); //默认 url 以 ? 结尾后挂参数
private static String DEFAULT_URL_END_MARK = "?";
//默认https协议 TLSv1
private String DEFAULT_HTTPS_PROTOCOLS = "TLSv1";
//默认请求方式 POST
private String DEFAULT_REQUEST_METHOD = "POST";
//默认接收所有格式
private String DEFAULT_ACCEPT = "*/*";
//默认字编码 UTF-8
private String DEFAULT_CHARSET = "UTF-8";
//默认发送数据格式
private String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded";
//默认请求后保持连接
private String DEFAULT_CONNECTION = "Keep-Alive";
//默认模拟浏览器发送
private String DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1";
//默认连接超时时间 6s
private int DEFAULT_CONNECT_TIMEOUT = 6 * 1000;
//默认读取超时时间 6s
private int DEFAULT_READ_TIMEOUT = 6 * 1000;
//接收到回复的成功码 200
private final static int RESPONSE_CODE_SUCCESS = 200;
//传入补充的消息头信息
private Map<String, String> HEADER_IN = null;
//发送证书给对方,默认不发送
private boolean CERT_SEND = false;
//验证对方发来的证书,默认不验证
private boolean CERT_AUTH = false;
//密钥库路径
private String KEYSTORE_PATH = "";
//密钥库密码
private String KEYSTORE_PASSWORD = "";
//信任证书库路径
private String TRUSTSTORE_PATH = "";
//信任证书库密码
private String TRUSTSTORE_PASSWORD = ""; /**
* 设置https协议 ,默认TLSv1
* @param protocols
*/
public void setHttpsProtocols(String protocols){
this.DEFAULT_HTTPS_PROTOCOLS = protocols;
} /**
* 设置字符编码,默认UTF-8
* @param charSet
*/
public void setCharSet(String charSet){
this.DEFAULT_CHARSET = charSet;
} /**
* 设置数据格式,默认application/x-www-form-urlencoded
* @param contentType
*/
public void setContentType(String contentType){
this.DEFAULT_CONTENT_TYPE = contentType;
} /**
* 设置连接超时时间 默认 6s
* @param connectTimeout
*/
public void setConnectTimeout(int connectTimeout){
this.DEFAULT_CONNECT_TIMEOUT = connectTimeout;
} /**
* 设置读取超时时间 默认 6s
* @param connectTimeout
*/
public void setReadTimeout(int readTimeout){
this.DEFAULT_READ_TIMEOUT = readTimeout;
} /**
* 传入补充消息头header信息
* @param headerIn
*/
public void setHeaderIn(Map<String, String> headerIn) {
this.HEADER_IN = headerIn;
} /**
* 如果对方需要验证本方证书,setKeyStore。[本方的证书应提前发送给对方,存入对方证书库。]
* KeyStore[存放本方密钥对的文件]。交互时,它会将本方证书自动发送过去,与对方信任证书库中的证书进行匹配。
* @param keyStorePath
* @param keyStorePassword
*/
public void setKeyStore(String keyStorePath, String keyStorePassword){
this.KEYSTORE_PATH = keyStorePath;
this.KEYSTORE_PASSWORD = keyStorePassword;
this.CERT_SEND = true;//从密钥库拿出证书发送给对方。
} /**
* 如果本方需要验证对方证书,setTrustStore。[拿到对方证书,提前存入我们的信任证书库]
* TrustStore[存放并信任对方证书的文件]。交互时,收到对方的证书会与trustStore中的证书进行匹配。
* @param keyStorePath
* @param keyStorePassword
*/
public void setTrustStore(String trustStorePath, String trustStorePassword){
this.TRUSTSTORE_PATH = trustStorePath;
this.TRUSTSTORE_PASSWORD = trustStorePassword;
this.CERT_AUTH = true;//信任库验证对方发来的证书。
} /**
* 发送请求
* @param urlStr url地址
* @param paramMap 请求参数Map
* @return
*/
public String post(String urlStr, Map<String, String> paramMap){
//默认不使用网络代理
return post(urlStr, paramMap, null);
} /**
* 发送请求
* @param urlStr url地址
* @param paramStr 请求参数Str
* @return
*/
public String post(String urlStr, String paramStr){
//默认不使用网络代理
return post(urlStr, paramStr, null);
} /**
* 发送请求
* @param urlStr url地址
* @param paramMap 请求参数Map
* @param proxyMap 如果需要添加网络代理,使用addProxy()方法获取。
* @return
*/
public String post(String urlStr, Map<String, String> paramMap, Map<String, Object> proxyMap){ String paramStr = paramMapToStr(paramMap); return post(urlStr, paramStr, proxyMap);
} /**
* 发送请求
* @param urlStr url地址
* @param paramIn 请求参数串
* @param proxyMap 如果需要添加网络代理,使用addProxy()方法获取。
* @return
*/
public String post(String urlStr, String paramIn, Map<String, Object> proxyMap){
Map<String, String> formatUrlMap = formatUrlStr(urlStr);
if(formatUrlMap==null||formatUrlMap.size()==0){
logger.info("url: " + urlStr);
logger.error("get url or param error...");
return "";
} urlStr = formatUrlMap.get("url");
logger.info("url address: "+urlStr); String urlParam = formatUrlMap.get("param");
String param = mergeParam(urlParam, paramIn); URLConnection urlConnection = getUrlConnection(urlStr, proxyMap);
if(urlConnection==null){
logger.error("create connection error...");
return "";
} HttpURLConnection httpURLConnection = null; if(urlStr.startsWith("https")){
logger.info("connection with https, set SSLContext...");
SSLSocketFactory sslSocketFactory = null;
try { System.setProperty("https.protocols", DEFAULT_HTTPS_PROTOCOLS); String sslContextType = "TLS";
if(DEFAULT_HTTPS_PROTOCOLS.toUpperCase().contains("TLS")){
sslContextType = "TLS";
} else if (DEFAULT_HTTPS_PROTOCOLS.toUpperCase().contains("SSL")){
sslContextType = "SSL";
} SSLContext sslContext = SSLContext.getInstance(sslContextType);
KeyManager[] keyManagers = initKeyManager();
TrustManager[] trustManagers = initTrustManager();
sslContext.init(keyManagers, trustManagers, new SecureRandom());
sslSocketFactory = sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} HttpsURLConnection httpsURLConnection = (HttpsURLConnection)urlConnection;
httpsURLConnection.setSSLSocketFactory(sslSocketFactory);
httpsURLConnection.setHostnameVerifier(initHostnameVerifier()); httpURLConnection = httpsURLConnection;
}else{
httpURLConnection = (HttpURLConnection)urlConnection;
} //如果有代理,查看是否有账号密码授权,进行授权
Map<String, String> proxyAccountInfo = getRequestPropertyInfoForProxy(proxyMap);
if(proxyAccountInfo!=null&&proxyAccountInfo.size()>0){
String propertyKey = proxyAccountInfo.get("key");
String propertyValue = proxyAccountInfo.get("value");
httpURLConnection.setRequestProperty(propertyKey, propertyValue);
}
//默认POST
try {
httpURLConnection.setRequestMethod(DEFAULT_REQUEST_METHOD);
} catch (ProtocolException e) {
e.printStackTrace();
}
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
httpURLConnection.setUseCaches(false);
httpURLConnection.setConnectTimeout(DEFAULT_READ_TIMEOUT);
httpURLConnection.setReadTimeout(DEFAULT_CONNECT_TIMEOUT);
httpURLConnection.setRequestProperty("accept", DEFAULT_ACCEPT);
httpURLConnection.setRequestProperty("connection", DEFAULT_CONNECTION);
httpURLConnection.setRequestProperty("User-Agent", DEFAULT_USER_AGENT);
httpURLConnection.setRequestProperty("Charset", DEFAULT_CHARSET);
httpURLConnection.setRequestProperty("Content-type", DEFAULT_CONTENT_TYPE + ";charset=" + DEFAULT_CHARSET);
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(param.length())); //补充header信息
addHeaderIn(httpURLConnection, HEADER_IN); BufferedWriter bw = null;
OutputStreamWriter osw = null;
OutputStream os = null;
try {
//post getOutputStream(),会自动调用connect()方法,所以不用再调用connect()
os = httpURLConnection.getOutputStream();
logger.info("connection connected..."); osw = new OutputStreamWriter(os, DEFAULT_CHARSET);
bw = new BufferedWriter(osw);
bw.write(param);
bw.flush(); logger.info("has been sent...");
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
if(bw!=null){
bw.close();
}
if(osw!=null){
osw.close();
}
if(os!=null){
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
} String result = null;
BufferedReader br = null;
InputStreamReader isr = null;
InputStream is = null;
try {
int responseCode = httpURLConnection.getResponseCode();
logger.info("response code: "+responseCode);
if(responseCode == RESPONSE_CODE_SUCCESS){
is = httpURLConnection.getInputStream();
isr = new InputStreamReader(is, DEFAULT_CHARSET);
br = new BufferedReader(isr); StringBuilder sb = new StringBuilder();
String temp = null;
while((temp=br.readLine())!=null){
sb.append(temp);
} result = sb.toString();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(br!=null){
br.close();
}
if(isr!=null){
isr.close();
}
if(is!=null){
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
} httpURLConnection.disconnect();
logger.info("connection close..."); logger.info("result: " + result);
return result;
} /**
* 传入补充消息头header信息
* @param headerIn
*/
private void addHeaderIn(HttpURLConnection httpURLConnection, Map<String, String> headerIn){
//传入补充消息头header信息
if(headerIn!=null&&headerIn.size()>0){
for(Map.Entry<String, String> entry : headerIn.entrySet()){
String key = entry.getKey();
String value = entry.getValue(); httpURLConnection.addRequestProperty(key, value);
}
}
} /**
* 获取URLConnection
* @param urlStr
* @param proxyMap
* @return
*/
private URLConnection getUrlConnection(String urlStr, Map<String, Object> proxyMap){
URLConnection urlConnection = null;
try {
URL url = new URL(urlStr); if(proxyMap!=null&&proxyMap.size()>0&&proxyMap.get("proxy")!=null){
Proxy proxy = (Proxy)proxyMap.get("proxy");
urlConnection = url.openConnection(proxy);
logger.info("use proxy...");
}else{
urlConnection = url.openConnection();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return urlConnection;
} /**
* 添加代理
* @param hostname
* @param port
* @param account
* @param password
* @return
*/
public Map<String, Object> addProxy(String hostname,int port,String account,String password){
Proxy proxy = null;
try {
InetSocketAddress address = new InetSocketAddress(hostname, port);
proxy = new Proxy(Proxy.Type.HTTP, address);
} catch (Exception e) {
e.printStackTrace();
logger.error("create proxy error...");
} Map<String, Object> map = new HashMap<String, Object>();
map.put("proxy", proxy);
map.put("account", account);
map.put("password", password);
return map;
} /**
* 如果有代理,查看是否有账号密码授权,进行授权,获取代理账户密码信息,并进行处理
* @param proxyMap
* @return
*/
private Map<String, String> getRequestPropertyInfoForProxy(Map<String, Object> proxyMap){
Map<String, String> map = new HashMap<String, String>();
if(proxyMap==null||proxyMap.size()==0){
return map;
}
Object proxyObj = proxyMap.get("proxy");
if(proxyObj==null){
return map;
} Object accountObj = proxyMap.get("account");
Object passwordObj = proxyMap.get("password"); String account = "";
if(accountObj!=null){
account = (String)accountObj;
}
String password = "";
if(passwordObj!=null){
password = (String)passwordObj;
} //如果有代理,查看是否有账号密码授权,进行授权
if(!"".equals(account)&&!"".equals(password)){
logger.info("proxy account: " + account + " / proxy pass: " + password);
String headerKey = "Proxy-Authorization"; String headerVal = "";
byte[] valByte = null;
try {
valByte = (account+": "+password).getBytes(DEFAULT_CHARSET);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if(valByte!=null&&valByte.length>0){
BASE64Encoder base64Encoder = new BASE64Encoder();
headerVal = "Basic " + base64Encoder.encode(valByte);
} map.put("key", headerKey);
map.put("value", headerVal);
} return map;
} /**
* 格式化url,获取?前边的url地址,及将后边附带的参数分离出来
* @param urlStr
* @return
*/
private static Map<String, String> formatUrlStr(String urlStr){
Map<String, String> map = new HashMap<String, String>();
if(urlStr==null||urlStr.trim().length()==0){
logger.error("url empty...");
return null;
} String url = urlStr;
String param = null;
if(urlStr.contains(DEFAULT_URL_END_MARK)){
int urlEndIndex = urlStr.indexOf(DEFAULT_URL_END_MARK);
url = urlStr.substring(0, urlEndIndex);
param = urlStr.substring(urlEndIndex + 1);
} if(!url.startsWith("http")){
if(url.startsWith("//")){
url = "http:" + url;
}else{
url = "http://" + url;
}
} map.put("url", url);
map.put("param", param);
return map;
} /**
* map类型的参数换成str参数。
* @param paramMap
* @return
*/
private static String paramMapToStr(Map<String, String> paramMap){
if(paramMap==null||paramMap.size()==0){
return "";
}
StringBuffer param = new StringBuffer();
for(Map.Entry<String, String> entry :paramMap.entrySet()){
String key = entry.getKey();
String value = entry.getValue();
param.append(key);
param.append("=");
param.append(value);
param.append("&");
}
return param.toString();
} /**
* 合并url中的参数及传入的参数
* @param urlParam
* @param paramStr
* @return
*/
private static String mergeParam(String urlParam, String paramStr){
if(urlParam==null||urlParam.trim().length()==0){
urlParam = "";
}
if(paramStr==null||paramStr.trim().length()==0){
paramStr = "";
} String param = "";
if(paramStr.startsWith(DEFAULT_URL_END_MARK)){
int markIndex = paramStr.indexOf(DEFAULT_URL_END_MARK);
paramStr = paramStr.substring(markIndex + 1);
if("".equals(urlParam)){
param = paramStr;
}else{
param = urlParam + "&" + paramStr;
}
} else if (paramStr.startsWith("&")){
if("".equals(urlParam)){
param = paramStr.substring(1);
}else{
param = urlParam + paramStr;
}
} else {
if("".equals(urlParam)){
param = paramStr;
}else{
param = urlParam + "&" + paramStr;
}
} logger.info("param str: " + param);
return param;
} /**
* 初始化keyStore
* @return
*/
private KeyManager[] initKeyManager(){
//从密钥库拿出证书发送给对方。
if(CERT_SEND){
File keyStoreFile = new File(KEYSTORE_PATH);
if(!(keyStoreFile.exists()&&keyStoreFile.isFile())){
logger.error("init keyStoreFile error...");
KeyManager[] keyManagers = {};
return keyManagers;//因为返回null,可以正常访问,所以采用这种写法,可以拦截住。
} InputStream keyStoreInput = null;
try {
keyStoreInput = new FileInputStream(keyStoreFile);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(keyStoreInput, KEYSTORE_PASSWORD.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, KEYSTORE_PASSWORD.toCharArray());
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
return keyManagers;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} finally {
if(keyStoreInput!=null){
try {
keyStoreInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
} KeyManager keyManager = new X509KeyManager() { @Override
public String[] getServerAliases(String arg0, Principal[] arg1) {
return null;
} @Override
public PrivateKey getPrivateKey(String arg0) {
return null;
} @Override
public String[] getClientAliases(String arg0, Principal[] arg1) {
return null;
} @Override
public X509Certificate[] getCertificateChain(String arg0) {
return null;
} @Override
public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2) {
return null;
} @Override
public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) {
return null;
}
}; KeyManager[] keyManagers = {keyManager};
return keyManagers;
} /**
* 初始化trustStore
* @return
*/
private TrustManager[] initTrustManager(){
//信任库验证对方发来的证书。
if(CERT_AUTH){
File trustStoreFile = new File(TRUSTSTORE_PATH);
if(!(trustStoreFile.exists()&&trustStoreFile.isFile())){
logger.error("init trustStoreFile error...");
TrustManager[] trustManagers = {};
return trustManagers;//因为返回null,可以正常访问,所以采用这种写法,可以拦截住。
} InputStream trustStoreInput = null;
try {
trustStoreInput = new FileInputStream(trustStoreFile);
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(trustStoreInput, TRUSTSTORE_PASSWORD.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
return trustManagers;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(trustStoreInput!=null){
try {
trustStoreInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
} TrustManager trustManager = new X509TrustManager() { @Override
public X509Certificate[] getAcceptedIssuers() {
return null;
} @Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException { } @Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException { }
}; TrustManager[] TrustManagers = {trustManager};
return TrustManagers;
} /**
* 域名验证,默认true验证通过
* @return
*/
private HostnameVerifier initHostnameVerifier(){
return new HostnameVerifier() { @Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
} }