当前位置 : 主页 > 编程语言 > java >

代理HTTP请求工具类

来源:互联网 收集:自由互联 发布时间:2021-06-28
收集于网络,按道理可发送HTTP或HTTPS的代理请求。由于条件限制,还未真正验证过,还请诸位大神指点。 package com.qhins.wcthl.utils;import java.io.BufferedReader;import java.io.IOException;import java.io
收集于网络,按道理可发送HTTP或HTTPS的代理请求。由于条件限制,还未真正验证过,还请诸位大神指点。
package com.qhins.wcthl.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.URL;
import java.net.URLConnection;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.log4j.Logger;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.util.StringUtils;

/**
 * 
 * 代理HTTP
* 
* @author 小精豆
* @version 【版本号, 2017年11月3日】
* @see 【相关类/方法】
* @since 【产品/模块版本】
 */
public class HTTPProxyUtils
{
    
    private static final Logger logger = Logger.getLogger(HTTPProxyUtils.class);

    private static final String HTTP = "http://";
    
    private static final String HTTPS = "https://";

    /**
     * HTTPS--代理POST请求
     * */
    public static String sendHttpsPostByProxy(String url, String param,
            String host, int port, String user, String password)
    {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try
        {
            URL realUrl = new URL(url);
            //指定信任HTTPS
            SSLContext ssl = SSLContext.getInstance("SSL");
            ssl.init(null,
                    new TrustManager[] { new TrustAnyTrustManager() },
                    new SecureRandom());
            //创建代理虽然是https也是Type.HTTP
            Proxy proxy = new Proxy(Type.HTTP,
                    new InetSocketAddress(host, port));
            // 打开和URL之间的连接
            HttpsURLConnection conn = (HttpsURLConnection) realUrl
                    .openConnection(proxy);
            //用户登录认证
            conn = handleAuth(user, password, conn);
            //设置https连接配置
            conn.setSSLSocketFactory(ssl.getSocketFactory());
            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setReadTimeout(10000);
            conn.setConnectTimeout(10000);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null)
            {
                result += line;
            }
            conn.disconnect();
        }
        catch (Exception e)
        {
            System.out.println("发送 POST 请求出现异常!" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally
        {
            try
            {
                if (out != null)
                {
                    out.close();
                }
                if (in != null)
                {
                    in.close();
                }
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
        return result;
    }
    
    /**
     * HTTP--代理POST请求
     * */
    public static String sendHttpPostByProxy(String url, String param,
            String host, int port, String user, String password)
    {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try
        {
            URL realUrl = new URL(url);
            //设置代理
            Proxy proxy = new Proxy(Type.HTTP,
                    new InetSocketAddress(host, port));
            // 打开和URL之间的连接
            HttpURLConnection conn = (HttpURLConnection) realUrl
                    .openConnection(proxy);
            //用户登录认证
            conn = handleAuth(user, password, conn);
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setReadTimeout(10000);
            conn.setConnectTimeout(10000);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null)
            {
                result += line;
            }
            conn.disconnect();
        }
        catch (Exception e)
        {
            System.out.println("发送 POST 请求出现异常!" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally
        {
            try
            {
                if (out != null)
                {
                    out.close();
                }
                if (in != null)
                {
                    in.close();
                }
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
        return result;
    }
    
    /**
    * 证书信任管理器
    * 
    * @author liuhy001
    * @version 【版本号, 2017年11月2日】
    * @see 【相关类/方法】
    * @since 【产品/模块版本】
     */
    private static class TrustAnyTrustManager implements X509TrustManager
    {
        /**
         * 该方法检查客户端的证书,若不信任该证书则抛出异常。
         * 由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。
         * JSSE中,默认的信任管理器类为TrustManager。
        * @param arg0
        * @param arg1
        * @throws CertificateException
         */
        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException
        {
        }
        
        /**
         * 该方法检查服务器的证书,若不信任该证书同样抛出异常。
         * 通过自己实现该方法,可以使之信任我们指定的任何证书。
         * 在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。
        * @param arg0
        * @param arg1
        * @throws CertificateException
         */
        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException
        {
        }
        
        /**
         * 返回受信任的X509证书数组。
        * @return
         */
        @Override
        public X509Certificate[] getAcceptedIssuers()
        {
            return new X509Certificate[] {};
        }
        
    }
    
    /**
    * 此类是用于主机名验证的基接口
    * 在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。
    * 策略可以是基于证书的或依赖于其他验证方案。
    * 当验证 URL 主机名使用的默认规则失败时使用这些回调。
    * 参数:
    * hostname - 主机名
    * session - 到主机的连接上使用的 SSLSession 
    * 返回: 如果主机名是可接受的,则返回 true
    * @author liuhy001
    * @version 【版本号, 2017年11月2日】
    * @see 【相关类/方法】
    * @since 【产品/模块版本】
     */
    private static class TrustAnyHostnameVerifier implements HostnameVerifier
    {
        
        @Override
        public boolean verify(String hostname, SSLSession session)
        {
            return true;
        }
        
    }
    
    /**
     * 发送代理请求 兼容http以及https
    * @param url
    * @param param
    * @param host
    * @param port
    * @return 【参数说明】
    * 
    * @return String 【返回类型说明】
    * @exception throws 【违例类型】 【违例说明】
    * @see 【类、类#方法、类#成员】
     */
    public static String sendPostByProxy(String url, String param, String host,
            int port, String user, String password)
    {
        if (StringUtils.isEmpty(url))
        {
            logger.info("...........请求路径不能为空");
            return null;
        }
        
        if (url.toLowerCase().startsWith(HTTPS))
        {
            //HTTPS
            return sendHttpsPostByProxy(url, param, host, port, user, password);
        }
        else if (url.toLowerCase().startsWith(HTTP))
        {
            //HTTP
            return sendHttpPostByProxy(url, param, host, port, user, password);
        }
        else
        {
            logger.info(".................请求协议有误");
        }
        return null;
    }
    
    
    /**
     * 用户登录认证
     * 
    * @param user
    * @param password
    * @param conn
    * @return 【参数说明】
    * 
    * @return T 【返回类型说明】
    * @exception throws 【违例类型】 【违例说明】
    * @see 【类、类#方法、类#成员】
     */
    public static 
 
   T handleAuth(String user, String password, T conn)
    {
        if (StringUtils.isEmpty(user) || StringUtils.isEmpty(password))
        {
            logger.info("............代理用户或者密码为空,不需要用户认证操作");
            return conn;
        }
        String headerkey = "Proxy-Authorization";
        String u_p = user + ":" + password;
        logger.info(".......代理服务器用户认证信息:" + u_p);
        String headerValue = "Basic "
                + Base64.encodeBase64String(u_p.getBytes()); //帐号密码用:隔开,base64加密方式  
        ((URLConnection) conn).setRequestProperty(headerkey, headerValue);
        return conn;
    }
}
 
网友评论