一尘不染

Java和HTTPS URL连接,无需下载证书

java

此代码连接到HTTPS站点,我假设我没有验证证书。但是,为什么我不必在本地为该站点安装证书?我是否应该不必在本地安装证书并为该程序加载证书,还是应将其下载到幕后?客户端到远程站点之间的通信是否仍在传输中加密?

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
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;

public class TestSSL {

    public static void main(String[] args) throws Exception {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        } };
        // Install the all-trusting trust manager
        final SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

        URL url = new URL("https://www.google.com");
        URLConnection con = url.openConnection();
        final Reader reader = new InputStreamReader(con.getInputStream());
        final BufferedReader br = new BufferedReader(reader);        
        String line = "";
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }        
        br.close();
    } // End of main 
} // End of the class //

阅读 205

收藏
2020-09-09

共1个答案

一尘不染

之所以不必在本地加载证书,是因为您已明确选择不使用该信任所有证书的信任管理器来验证证书。

流量仍将被加密,但是您正在打开与中间人攻击的连接:您正在与某人秘密通信,只是不确定它是您期望的服务器还是潜在的攻击者。

如果您的服务器证书来自一个著名的CA,它是与JRE捆绑在一起的默认CA证书捆绑的一部分(通常是cacerts文件,请参见JSSE参考指南),则可以使用默认信任管理器,而不必设置这里的任何东西。

如果您拥有特定的证书(自签名证书或来自您自己的CA),则可以使用默认的信任管理器,也可以使用通过特定信任库初始化的证书,但必须将证书显式导入到信任存储中(独立后)。验证)

2020-09-09