Java 里面访问 https 链接不验证

通常使用一些 http 的客户端工具包,如 apache 等,无法访问 https 的链接(使用 HTTPS 专用的Client ),主要是因为底层实现本身就是两套通信。

而且 https 一般需要有证书信任才行,实际上这个是客户端的限制,由于项目中需要同时调用 http 和 https(连证书都没有的,没办法),所以只有自己写一个了。

记录一下,同时支持HTTP和HTTPS访问。

基本上访问一个HTTP的代码如下,兼容了HTTPS访问(没有证书认证的,如果想访问支付宝等,需要配置一个访问的公钥)

public class HttpClient {
    private String charset = "UTF-8";
    
    private boolean safe = false;

    private String url;

    Map<String, String> headers = null;

    public HttpClient(String url) {
        this.url = url;
        this.safe = url.startsWith("https");
    }

    public HttpClient(String url, String charset) {
        this.url = url;
        this.charset = charset;
        this.safe = url.startsWith("https");
    }

    public void setHeader(Map<String, String> headers) {
        this.headers = headers;
    }

    public String get() throws IOException {
        if (this.safe) {
            return this.sendhttpsReq("GET", "", headers);
        } else {
            return this.sendhttpReq("GET", "", headers);
        }
    }

    public String post(String httpStr) throws IOException {
        if (this.safe) {
            return this.sendhttpsReq("POST", "", headers);
        } else {
            return this.sendhttpReq("POST", "", headers);
        }
    }

    /**
     * 发送http请求.
     * @param url
     *            :请求url
     * @param httpStr
     *            :请求消息体
     * @param headers
     *            :请求消息头
     * @return http返回消息体,null表示失败
     * @throws IOException
     */
    private final String sendhttpReq(String method, String httpStr,
            Map<String, String> headers) throws IOException {
        HttpURLConnection conn = (HttpURLConnection) new URL(url)
                .openConnection();
        conn.setRequestMethod(method);
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setRequestProperty("Content-Type", "text/heml");
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                conn.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
        OutputStream out = conn.getOutputStream();
        out.write(httpStr.getBytes(charset));
        out.flush();
        BufferedReader in = new BufferedReader(new InputStreamReader(
                conn.getInputStream()));
        if (200 != conn.getResponseCode()) {
            return null;
        }
        StringBuilder result = new StringBuilder(100);
        char[] buf = new char[512];
        int byteread = 0;
        while ((byteread = in.read(buf)) != -1) {
            result.append(buf, 0, byteread);
        }
        return result.toString();
    }
    /**
     * 发送https请求.
     * @param url
     *            :请求url
     * @param httpStr
     *            :请求消息体
     * @param headers
     *            :请求消息头
     * @return http返回消息体,null表示失败
     * @throws IOException
     */
    private final String sendhttpsReq(String method, String httpStr,
            Map<String, String> headers) {
        HttpsURLConnection conn = null;  
        OutputStream out = null;  
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom()); 
            SSLContext.setDefault(ctx); 
            conn = (HttpsURLConnection) new URL(url).openConnection();  
            conn.setRequestMethod(method);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setHostnameVerifier(new HostnameVerifier(){
                @Override  
                public boolean verify(String hostname, SSLSession session) {  
                    return true;  
                }
            });
            conn.setRequestProperty("Content-Type", "text/html");
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    conn.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }
            out = conn.getOutputStream();
            out.write(httpStr.getBytes(charset));
            out.flush();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            if (200 != conn.getResponseCode()) {
                return null;
            }
            StringBuilder result = new StringBuilder(100);
            char[] buf = new char[512];
            int byteread = 0;
            while ((byteread = in.read(buf)) != -1) {
                result.append(buf, 0, byteread);
            }
            return result.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    private static class DefaultTrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }
        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }

    public static void main(String[] args){
        HttpClient client = new HttpClient("http://www.qq.com/");
        try {
            System.out.println(client.get());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        };
        HttpClient client2 = new HttpClient("https://localhost:8443/login");
        try {
            System.out.println(client2.post("username=d&password=ddd"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        };
    }
}