使用URLConnection进行访问

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

 jdk1.8以上环境才支持TLSv1.2,如果是jdk1.6环境的话代码中DEFAULT_HTTPS_PROTOCOLS需要赋值等于TLS。并且base64方法也需要换成1.6版本的。

支持双向验证。如果对方要验证我们发送的证书,发送前先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.Arrays;
import java.util.Base64;
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;

public class HttpUtil {
    private static Logger logger = Logger.getLogger(HttpUtil.class);
    //默认https协议 TLSv1.2
    private String DEFAULT_HTTPS_PROTOCOLS = "TLSv1.2";
    //默认请求方式 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.2
     * @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 = "TLSv1.2";
                if(DEFAULT_HTTPS_PROTOCOLS.toUpperCase().contains("TLS")){
                    sslContextType = DEFAULT_HTTPS_PROTOCOLS;
                }
                
                SSLContext sslContext = SSLContext.getInstance(sslContextType);
                KeyManager[] keyManagers = initKeyManager();
                TrustManager[] trustManagers = initTrustManager();
                sslContext.init(keyManagers, trustManagers, new SecureRandom());
                sslSocketFactory = sslContext.getSocketFactory();
                
                String[] protocolsInfo = sslContext.getDefault().getSupportedSSLParameters().getProtocols();
                logger.info("Supported protocols:"+Arrays.toString(protocolsInfo));
                
                HttpsURLConnection httpsURLConnection = (HttpsURLConnection)urlConnection;
                httpsURLConnection.setSSLSocketFactory(sslSocketFactory);
                httpsURLConnection.setHostnameVerifier(initHostnameVerifier());
                httpURLConnection = httpsURLConnection;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            httpURLConnection = (HttpURLConnection)urlConnection;
        }
        
        if(httpURLConnection==null){
            logger.error("create connect error...");
            return null;
        }
        
        //如果有代理,查看是否有账号密码授权,进行授权
        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){
                headerVal = "Basic " + Base64.getEncoder().encodeToString(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;
            }
        };
    }
    
}

 

posted @ 2018-03-09 14:49  新手娃娃菜  阅读(360)  评论(0编辑  收藏  举报