Java 关於发送 Https 请求 (HttpsURLConnection 和 HttpURLConnection)

https 协议对於开发者而言其实只是多了一步证书验证的过程,这个证书正常情况下被 jdk/jre/security/cacerts 所管理,里面证书包含两种情况:

1、机构所颁发的被认证的证书,这种证书的网站在浏览器访问时 https 头显示爲绿色

2、个人所设定的证书,这种证书的网站在浏览器里 https 头显示爲红色 ×,且需要点击信任该网站才能继续访问,。而点击信任这一步的操作就是我们在 java 代码访问 https 网站时区别於 http 请求需要做的事情。

所以 JAVA 发送 https 请求有两种情况,三种解决办法:

第一种情况:https 网站的证书爲机构所颁发的被认证的证书,这种情况下和 http 请求一模一样无需做任何改变,用 HttpsURLConnection 或者 HttpURLConnection 都可以

    public static void main(String[] args) throws Exception{
        URL serverUrl = new URL("https://xxxx");
        HttpURLConnection conn = 
            (HttpURLConnection) serverUrl.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-type", "application/json");
        conn.setInstanceFollowRedirects(false);
        conn.connect();
        String result = Sender.getReturn(conn);
    }

    public static String getReturn(HttpURLConnection connection)
        throws Exception{
        StringBuffer buffer = new StringBuffer();

        try(InputStream inputStream = connection.getInputStream();
                InputStreamReader inputStreamReader = 
                    new InputStreamReader(inputStream,
                        java.lang.invoke.ConstantInfo.CHARSET);
                    BufferedReader bufferedReader = 
                        new BufferedReader(inputStreamReader);) {
            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            String result = buffer.toString();
            return result;
        }
    }

第二种情况:个人所设定的证书,这种证书默认不被信任,需要我们自己选择信任,信任的办法有两种

A、将证书导入java的运行环境中

从该网站下载或者从网站开发者出获取证书 cacert.crt 运行命令将证书导入 java 运行环境:keytool -import -keystore %JAVA_HOME%\jre\lib\security\cacerts -file cacert.crt -alias xxx
完成,java 代码中发送 https 的请求和 http 一样,同第一种情况。

B、忽略证书验证过程,忽略之後任何 https协议网站皆能正常访问,同第一种情况

import java.net.URL;
import java.security.cert.*;
import javax.net.ssl.*;

public class MyX509TrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate certificates[],
        String authType) throws CertificateException {
    }

    @Override
    public void checkServerTrusted(X509Certificate[] ax509certificate,
    String s) throws CertificateException {
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

public static void main(String[] args) throws Exception {
        SSLContext sc = SSLContext.getInstance("TLSv1.2", "SunJSSE");
        
        sc.init(null,
            new TrustManager[] {new MyX509TrustManager() },
                new java.security.SecureRandom());
        
        SSLSocketFactory ssf = sc.getSocketFactory();
        
        URL url = new URL("https://xxx.com.tw");
        
        HttpsURLConnection httpsConn =
           (HttpsURLConnection) url.openConnection();
        
        HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
            public boolean verify(String s, SSLSession sslsession) {
                System.out.println(
                    "WARNING: Hostname is not matched for cert."
                );
                return true;
            }
        };
        
        httpsConn.setDefaultHostnameVerifier(ignoreHostnameVerifier);
        httpsConn.setDefaultSSLSocketFactory(ssf);
}

C、java 代码中加载证书,必须使用 HttpsURLConnection 方式,从网站开发者出获取生成证书的密钥库 cacert.keystore

import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class MyX509TrustManager implements X509TrustManager {

    X509TrustManager sunJSSEX509TrustManager;
    MyX509TrustManager() throws Exception {

        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(new FileInputStream("cancert.keystore"),
            "changeit".toCharArray());

        TrustManagerFactory tmf =
            TrustManagerFactory.getInstance("SunX509", "SunJSSE");

        tmf.init(ks);
        TrustManager tms [] = tmf.getTrustManagers();

        for (int i = 0; i < tms.length; i++) {
            if (tms[i] instanceof X509TrustManager) {
                sunJSSEX509TrustManager = (X509TrustManager) tms[i];
                return;
            }
        }

        throw new Exception("Couldn't initialize");
    }

    public void checkClientTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        try {
            sunJSSEX509TrustManager.checkClientTrusted(chain, authType);
        } catch (CertificateException excep) {

        }
    }

    public void checkServerTrusted(X509Certificate[] chain,
        String authType) throws CertificateException {
        try {
            sunJSSEX509TrustManager.checkServerTrusted(chain, authType);
        } catch (CertificateException excep) {

        }
    }

    public X509Certificate[] getAcceptedIssuers() {
        return sunJSSEX509TrustManager.getAcceptedIssuers();
    }
}

public static void main(String[] args) throws Exception {
    SSLContext sslcontext =
        SSLContext.getInstance("SSL","SunJSSE");

    sslcontext.init(null, new TrustManager[]{new MyX509TrustManager()},
        new java.security.SecureRandom());

    URL serverUrl = new URL("https://xxxx");
    HttpsURLConnection conn = (HttpsURLConnection) serverUrl.openConnection();

    conn.setSSLSocketFactory(sslcontext.getSocketFactory());
    conn.setRequestMethod("GET");
    conn.setRequestProperty("Content-type", "application/json");
    conn.setInstanceFollowRedirects(false);
    conn.connect();

    String result = getReturn(conn);
}

public static String getReturn(HttpsURLConnection connection)
    throws IOException {

    StringBuffer buffer = new StringBuffer();

    try (InputStream inputStream = connection.getInputStream();

            InputStreamReader inputStreamReader =
                new InputStreamReader(inputStream,
                    ConstantInfo.CHARSET);

            BufferedReader bufferedReader =
                new BufferedReader(inputStreamReader);
        )
        {

            String str = null;

            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            String result = buffer.toString();
            return result;
        }
}

<<:  Linux 更改档案或目录的权限

>>:  谁有百度帐号~可以帮我下载个影片

[第04天]理财达人Mx. Ada-历史交易资料

前言 本文说明取得历史交易资料。 程序实作 取得历史tick资料 tick代表每一笔成交纪录。 # ...

谈谈JSON

由wiki(https://zh.wikipedia.org/wiki/JSON) 可以知道JSON...

Day17 发生广告被拒登的原因?

你可能精心写了一段广告,但最後发现被 Google 拒登,但别担心,这个情况,也许每个人都曾经历过。...

Day29-保护鲸鱼人人有责(四)

前言 前几天不管是讲怎麽把 Dockerfile 写好、还是做弱点扫描,基本上都是在确保 Docke...

Day 03 | 透过指令建立元件

安装并部署 Livewire 的步骤没有很多,照着做不用三分钟就能完成罗!今天一样是照着官方文件带大...