iT邦幫忙

1

Java 關於發送 Https 請求 (HttpsURLConnection 和 HttpURLConnection)

  • 分享至 

  • xImage
  •  

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;
        }
}

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言