簡體   English   中英

使用給定的 p12 證書連接到 https 站點

[英]Connect to a https site with a given p12 certificate

服務器端給了我一個.p12證書文件,我點擊並安裝在我的機器上,然后我可以通過瀏覽器訪問HTTPS站點。 現在他們希望我使用給定的證書抓取他們的網站。 我被困在它的第一階段,試圖從httpsURLConnection獲取inputStream 該網站沒有登錄。 它只檢查您是否擁有證書。

到目前為止,我所做的是使用 Firefox 以.crt文件格式導出證書。 然后我使用 keytool 命令將它( .crt文件,而不是.p12 )導入到 java 密鑰庫中。 然后在代碼中:

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
File ksFile = new File(keystorePath);
in = new FileInputStream(ksFile);
ks.load(in, "changeit".toCharArray());
X509Certificate cert = (X509Certificate) ks.getCertificate(certificateAlias);

SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

HttpsURLConnection con = (HttpsURLConnection) (new URL(urlString)).openConnection();
con.connect();
con.getInputStream();
con.disconnect();

getInputStream()會給我 403 錯誤禁止訪問。 我搜索了其他相關主題,實際上比閱讀它們之前更加困惑。 非常感謝答案。

額外細節:

  • 我剛剛實例化了證書,並沒有讓程序知道任何類型的密鑰(私有、公共等)。 所以我認為我必須將這些密鑰提供給服務器,讓它知道我實際上持有證書。 我完全不知道如何做到這一點,無論是邏輯還是語法。
  • 我已嘗試使用 keytool 命令將 .p12 證書文件導入密鑰庫,但不知何故,keytool 無法識別 -pkcs12 選項。 關於如何直接使用這個 .p12 證書的任何想法也會很棒。
  • trustAllCert 是 TrustMangers 的單元素數組,它不驗證任何內容(信任所有內容)。 我不知道我是否應該繼續使用這個。 事實上,現在我實際上只有一個可以信任的證書。 在這種情況下編寫 trustManger 的正確方法是什么?
  • 我無法控制服務器端。 我得到的只是訪問他們網站的 URL,它是在 HTTPS 協議下的,以及一個 .p12 證書。 該網站沒有登錄。 如果安裝了證書,我就可以進去了。

如果您想嘗試對 SSL 配置進行編碼,您可以使用提供給您的 P12 文件,而無需將其轉換為 JKS。 此外,您將需要使用 P12 中的私鑰,而不僅僅是您復制到 JKS 中的證書。 不確定這是否會直接滿足您的需求,但這可能會讓您走上正確的道路:

        KeyStore clientStore = KeyStore.getInstance("PKCS12");
        clientStore.load(new FileInputStream("test.p12"), "testPass".toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(clientStore, "testPass".toCharArray());
        KeyManager[] kms = kmf.getKeyManagers();

        KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(new FileInputStream("cacerts"), "changeit".toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
        TrustManager[] tms = tmf.getTrustManagers();

        SSLContext sslContext = null;
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kms, tms, new SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        URL url = new URL("https://www.testurl.com");

        HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection();

以這種方式配置 trustStore 是可選的。 您可以使用 P12 鏈中的所有證書創建 JKS,或者只需確保它們在您的 JRE 的 cacerts 文件中。 至於keytool,作為參考,您可以在P12 上運行keytool 命令(指定-storetype pkcs12),但不能將P12 導入JKS。 您也不能使用 keytool 命令僅從 P12 導出密鑰。

我目前沒有設置服務器來測試此代碼,因此請試一試,看看您是否仍然收到 403 錯誤。

這對我有用:

   KeyStore keyStore  = KeyStore.getInstance("PKCS12");
    FileInputStream instream = new FileInputStream(new File("client-p12-keystore.p12"));
    try {
        keyStore.load(instream, "password".toCharArray());
    } finally {
        instream.close();
    }

    // Trust own CA and all self-signed certs
    SSLContext sslcontext = SSLContexts.custom()
        .loadKeyMaterial(keyStore, "password".toCharArray())
        //.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
        .build();
    // Allow TLSv1 protocol only
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
        sslcontext,
        SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    CloseableHttpClient httpclient = HttpClients.custom()
        .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
        .setSSLSocketFactory(sslsf)
        .build();
    try {

        HttpGet httpget = new HttpGet("https://localhost:8443/secure/index");

        System.out.println("executing request" + httpget.getRequestLine());

        CloseableHttpResponse response = httpclient.execute(httpget);
        try {
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
            }
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}

添加這個作為答案,因為我需要更多的空間來寫。

首先,一個問題:證書是由威瑞信等可信權威機構簽署的嗎? 如果不是,則信任庫應具有使 p12 證書“有效”的 CA 證書(通常是 .pem 文件)。 默認的 Java 信任存儲包含來自大公司(例如 Verisign 和 Thawte)的大部分(如果不是全部)CA 證書。

此外,您可以測試您的應用程序以連接到安全服務器,而無需對 SSL 配置進行編碼,但使用一些命令行參數,例如:

java -Djavax.net.ssl.keyStore=[path_to_p12_cert] \
 -Djavax.net.ssl.keyStorePassword=[p12_password] \
 -Djavax.net.ssl.keyStoreType=PKCS12 \
 -Djavax.net.ssl.trustStore=[path_to_trust_store_with_CA_certificates] \
 -Djavax.net.ssl.trustStorePassword=[trust_store_password] \
 [MainClass]

然后你的代碼就變成了

HttpsURLConnection con = (HttpsURLConnection) (new URL(urlString)).openConnection();
con.connect();
con.getInputStream();
con.disconnect();

如果您感到受虐狂, JSSE 參考指南非常有趣。

如果您使用的是 Spring,則可以通過 RestTemplate 訪問它:

public RestTemplate restTemplate() throws Exception {
    KeyStore clientStore = KeyStore.getInstance("PKCS12");
    InputStream resource = this.getClass().getClassLoader().getResourceAsStream("path_to_certificate.p12");
    clientStore.load(resource, "p12_password".toCharArray());

    SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
    sslContextBuilder.setProtocol("TLS");
    sslContextBuilder.loadKeyMaterial(clientStore, "p12_password".toCharArray());
    sslContextBuilder.loadTrustMaterial(new TrustSelfSignedStrategy());

    SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContextBuilder.build());
    CloseableHttpClient httpClient = HttpClients.custom()
        .setSSLSocketFactory(sslConnectionSocketFactory)
        .build();
    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
    return new RestTemplate(requestFactory);
}

簡單的 keytool 命令會將您的 .p12 密鑰庫導出到 .jks 密鑰庫:

keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore keystore.jks

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM