用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.net.URLEncoder; 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); //默认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 url url地址 * @param paramMap 请求参数Map * @return */ public String post(String url, Map<String, String> paramMap){ //默认不使用网络代理 return post(url, paramMap, null); } /** * 发送请求 * @param url url地址 * @param param 请求参数Str * @return */ public String post(String url, String param){ //默认不使用网络代理 return post(url, param, null); } /** * 发送请求 * @param url url地址 * @param paramMap 请求参数Map * @param proxyMap 如果需要添加网络代理,使用本类的addProxy()方法获取并添加。 * @return */ public String post(String url, Map<String, String> paramMap, Map<String, Object> proxyMap){ String param = paramMapToStr(paramMap); return post(url, param, proxyMap); } /** * 发送请求 * @param url url地址 * @param param 请求参数串 * @param proxyMap 如果需要添加网络代理,使用addProxy()方法获取。 * @return */ public String post(String url, String param, Map<String, Object> proxyMap){ url = formatUrl(url); logger.info("url address: "+url); if(url==null||url.trim().length()==0){ logger.error("get url error..."); return ""; } if(param==null||param.trim().length()==0){ param = ""; } URLConnection urlConnection = getUrlConnection(url, proxyMap); if(urlConnection==null){ logger.error("create connection error..."); return ""; } HttpURLConnection httpURLConnection = null; if(url.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 = ""; 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 url * @param proxyMap * @return */ private URLConnection getUrlConnection(String url, Map<String, Object> proxyMap){ URLConnection urlConnection = null; try { URL urlObject = new URL(url); if(proxyMap!=null&&proxyMap.size()>0&&proxyMap.get("proxy")!=null){ Proxy proxy = (Proxy)proxyMap.get("proxy"); urlConnection = urlObject.openConnection(proxy); logger.info("use proxy..."); }else{ urlConnection = urlObject.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 url * @return */ private static String formatUrl(String url){ if(url==null||url.trim().length()==0){ logger.error("url empty..."); return ""; } if(!url.startsWith("http")){ if(url.startsWith("//")){ url = "http:" + url; }else{ url = "http://" + url; } } return url; } /** * map类型的参数换成str参数。 * @param paramMap * @return */ private String paramMapToStr(Map<String, String> paramMap){ if(paramMap==null||paramMap.size()==0){ return ""; } StringBuffer param = new StringBuffer(); try { for(Map.Entry<String, String> entry :paramMap.entrySet()){ String key = entry.getKey(); String value = entry.getValue(); value = (value==null?"":value); param.append(key); param.append("="); param.append(URLEncoder.encode(value, DEFAULT_CHARSET)); param.append("&"); } } catch (Exception e) { e.printStackTrace(); } return param.toString(); } /** * 初始化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; } }; } }