Xác thực chứng chỉ ứng dụng khách HTTPS của Java


222

Tôi còn khá mới HTTPS/SSL/TLSvà tôi hơi bối rối về chính xác những gì khách hàng sẽ trình bày khi xác thực bằng chứng chỉ.

Tôi đang viết một máy khách Java cần thực hiện một POSTdữ liệu đơn giản URL. Phần đó hoạt động tốt, vấn đề duy nhất là nó phải được hoàn thành HTTPS. Phần HTTPSnày khá dễ xử lý (có HTTPclienthoặc sử dụng HTTPShỗ trợ tích hợp sẵn của Java ), nhưng tôi bị kẹt khi xác thực bằng chứng chỉ ứng dụng khách. Tôi đã nhận thấy rằng đã có một câu hỏi tương tự ở đây, mà tôi chưa thử với mã của mình (sẽ sớm thực hiện). Vấn đề hiện tại của tôi là - bất cứ điều gì tôi làm - máy khách Java không bao giờ gửi cùng với chứng chỉ (tôi có thể kiểm tra điều này với các PCAPbãi chứa).

Tôi muốn biết chính xác ứng dụng khách nào sẽ trình bày với máy chủ khi xác thực bằng chứng chỉ (cụ thể cho Java - nếu điều đó có vấn đề gì không)? Đây là một JKStập tin, hay PKCS#12? Những gì được cho là ở trong họ; chỉ là chứng chỉ ứng dụng khách, hay chìa khóa? Nếu vậy, chìa khóa nào? Có khá nhiều nhầm lẫn về tất cả các loại tệp, loại chứng chỉ khác nhau, v.v.

Như tôi đã nói trước đây tôi mới biết HTTPS/SSL/TLSnên tôi cũng sẽ đánh giá cao một số thông tin cơ bản (không phải là một bài tiểu luận; tôi sẽ giải quyết các liên kết đến các bài viết hay).


Tôi đã đưa ra hai chứng chỉ từ khách hàng về cách xác định cái nào cần thêm trong kho khóa và cửa hàng tin cậy, bạn có thể giúp xác định vấn đề này vì bạn đã trải qua loại vấn đề tương tự, vấn đề này tôi đã nêu ra thực sự không biết phải làm gì với stackoverflow .com / câu hỏi / 61374276 / đánh
henrycharles

Câu trả lời:


233

Cuối cùng quản lý để giải quyết tất cả các vấn đề, vì vậy tôi sẽ trả lời câu hỏi của riêng tôi. Đây là các cài đặt / tệp tôi đã sử dụng để quản lý để giải quyết (các) vấn đề cụ thể của mình;

Kho khóa của khách hàng là tệp định dạng PKCS # 12 có chứa

  1. Chứng chỉ công khai của khách hàng (trong trường hợp này được ký bởi CA tự ký)
  2. Của khách hàng cá nhân chủ chốt

Để tạo ra nó, tôi đã sử dụng pkcs12lệnh của OpenSSL , ví dụ;

openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "Whatever"

Mẹo: đảm bảo bạn nhận được OpenSSL mới nhất, không phải phiên bản 0.9.8h vì dường như đó là lỗi không cho phép bạn tạo các tệp PKCS # 12 đúng cách.

Tệp PKCS # 12 này sẽ được máy khách Java sử dụng để xuất trình chứng chỉ ứng dụng khách cho máy chủ khi máy chủ yêu cầu rõ ràng máy khách xác thực. Xem bài viết Wikipedia trên TLS để biết tổng quan về cách giao thức xác thực chứng chỉ ứng dụng khách thực sự hoạt động (cũng giải thích lý do tại sao chúng tôi cần khóa riêng của khách hàng ở đây).

Cửa hàng ủy thác của khách hàng là một tệp định dạng JKS chuyển tiếp chứa các chứng chỉ CA gốc hoặc trung gian . Các chứng chỉ CA này sẽ xác định điểm cuối nào bạn sẽ được phép liên lạc, trong trường hợp này, nó sẽ cho phép khách hàng của bạn kết nối với bất kỳ máy chủ nào xuất trình chứng chỉ được ký bởi một trong các CA của Truststore.

Để tạo ra nó, bạn có thể sử dụng keytool Java tiêu chuẩn, ví dụ;

keytool -genkey -dname "cn=CLIENT" -alias truststorekey -keyalg RSA -keystore ./client-truststore.jks -keypass whatever -storepass whatever
keytool -import -keystore ./client-truststore.jks -file myca.crt -alias myca

Sử dụng cửa hàng tin cậy này, khách hàng của bạn sẽ cố gắng thực hiện bắt tay SSL hoàn chỉnh với tất cả các máy chủ xuất trình chứng chỉ được ký bởi CA được xác định bởi myca.crt.

Các tập tin trên chỉ dành cho khách hàng. Khi bạn cũng muốn thiết lập một máy chủ, máy chủ cần các tệp tin và kho khóa riêng. Có thể tìm thấy một hướng dẫn tuyệt vời để thiết lập một ví dụ hoạt động đầy đủ cho cả máy khách và máy chủ Java (sử dụng Tomcat) trên trang web này .

Vấn đề / Nhận xét / Mẹo

  1. Xác thực chứng chỉ ứng dụng khách chỉ có thể được thực thi bởi máy chủ.
  2. ( Quan trọng! ) Khi máy chủ yêu cầu chứng chỉ ứng dụng khách (như một phần của bắt tay TLS), nó cũng sẽ cung cấp danh sách các CA đáng tin cậy như một phần của yêu cầu chứng chỉ. Khi chứng chỉ ứng dụng khách bạn muốn xuất trình để xác thực không được ký bởi một trong những CA này, nó sẽ không được trình bày (theo tôi, đây là hành vi kỳ lạ, nhưng tôi chắc chắn có lý do cho điều đó). Đây là nguyên nhân chính gây ra sự cố của tôi, vì bên kia đã không cấu hình đúng máy chủ của họ để chấp nhận chứng chỉ ứng dụng khách tự ký của tôi và chúng tôi cho rằng vấn đề nằm ở phía tôi vì đã không cung cấp đúng chứng chỉ ứng dụng khách trong yêu cầu.
  3. Nhận Wireshark. Nó có phân tích gói SSL / HTTPS tuyệt vời và sẽ giúp ích rất nhiều cho việc gỡ lỗi và tìm ra vấn đề. Nó tương tự -Djavax.net.debug=sslnhưng có cấu trúc chặt chẽ hơn và (có thể nói là) dễ hiểu hơn nếu bạn không thoải mái với đầu ra gỡ lỗi Java SSL.
  4. Hoàn toàn có thể sử dụng thư viện httpclient của Apache. Nếu bạn muốn sử dụng httpclient, chỉ cần thay thế URL đích bằng tương đương HTTPS và thêm các đối số JVM sau (tương tự cho mọi máy khách khác, bất kể thư viện bạn muốn sử dụng để gửi / nhận dữ liệu qua HTTP / HTTPS) :

    -Djavax.net.debug=ssl
    -Djavax.net.ssl.keyStoreType=pkcs12
    -Djavax.net.ssl.keyStore=client.p12
    -Djavax.net.ssl.keyStorePassword=whatever
    -Djavax.net.ssl.trustStoreType=jks
    -Djavax.net.ssl.trustStore=client-truststore.jks
    -Djavax.net.ssl.trustStorePassword=whatever

6
"Khi chứng chỉ ứng dụng khách bạn muốn xuất trình để xác thực không được ký bởi một trong những CA này, nó sẽ không được trình bày". Chứng chỉ không được xuất trình vì khách hàng biết rằng họ sẽ không được máy chủ chấp nhận. Ngoài ra, chứng chỉ của bạn có thể được ký bởi CA "ICA" trung gian và máy chủ có thể cung cấp cho khách hàng của bạn với CA "RCA" gốc và trình duyệt web của bạn sẽ vẫn cho phép bạn chọn chứng chỉ của mình mặc dù được ký bởi ICA chứ không phải RCA.
KyleM

2
Như một ví dụ về nhận xét trên, hãy xem xét một tình huống trong đó bạn có một CA gốc (RCA1) và hai CA trung gian (ICA1 và ICA2). Trên Apache Tomcat nếu bạn nhập RCA1 vào cửa hàng ủy thác, trình duyệt web của bạn sẽ xuất hiện TẤT CẢ các chứng chỉ được ký bởi ICA1 và ICA2, mặc dù chúng không có trong cửa hàng tin cậy của bạn. Điều này là bởi vì đó là chuỗi quan trọng không phải là certs cá nhân.
KyleM

2
"Theo tôi, đây là hành vi kỳ lạ, nhưng tôi chắc chắn có lý do cho điều đó". Lý do cho điều đó là những gì nó nói trong RFC 2246. Không có gì lạ về nó. Cho phép khách hàng xuất trình chứng chỉ không được máy chủ chấp nhận là điều kỳ lạ và hoàn toàn lãng phí thời gian và không gian.
Hầu tước Lorne

1
Tôi thực sự khuyên bạn không nên sử dụng một kho khóa, toàn bộ JVM (và Truststore!) Như bạn có trong ví dụ trên. Tùy chỉnh một kết nối duy nhất sẽ an toàn và linh hoạt hơn, nhưng nó yêu cầu bạn phải viết thêm một chút mã. Bạn phải tùy chỉnh SSLContextcâu trả lời của @ Magnus.
Christopher Schultz

63

Các câu trả lời khác cho thấy cách cấu hình toàn cầu chứng chỉ ứng dụng khách. Tuy nhiên, nếu bạn muốn xác định theo cách lập trình khóa máy khách cho một kết nối cụ thể, thay vì xác định toàn cầu nó trên mọi ứng dụng chạy trên JVM của bạn, thì bạn có thể định cấu hình SSLContext của riêng mình như vậy:

String keyPassphrase = "";

KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("cert-key-pair.pfx"), keyPassphrase.toCharArray());

SSLContext sslContext = SSLContexts.custom()
        .loadKeyMaterial(keyStore, null)
        .build();

HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpResponse response = httpClient.execute(new HttpGet("https://example.com"));

Tôi đã phải sử dụng sslContext = SSLContexts.custom().loadTrustMaterial(keyFile, PASSWORD).build();. Tôi không thể làm cho nó làm việc với loadKeyMaterial(...).
Conor Svensson

4
Tài liệu tin cậy @ConorSvensson dành cho khách hàng tin tưởng chứng chỉ máy chủ từ xa, tài liệu chính dành cho máy chủ tin tưởng khách hàng.
Magnus

1
Tôi thực sự thích câu trả lời súc tích và đúng điểm này. Trong trường hợp mọi người quan tâm, tôi cung cấp một ví dụ hoạt động ở đây với hướng dẫn xây dựng. stackoverflow.com/a/46821977/154527
Alain O'Dea

3
Bạn đã cứu ngày của tôi! Chỉ cần một thay đổi thêm tôi phải làm, gửi mật khẩu bằng loadKeyMaterial(keystore, keyPassphrase.toCharArray())mã '!
AnandShanbhag

1
@peterh Có, nó dành riêng cho Apache http. Mỗi thư viện HTTP sẽ có cách cấu hình riêng, nhưng hầu hết chúng nên sử dụng một cách nào đó SSLContext.
Magnus

30

Tệp JKS của họ chỉ là một thùng chứa chứng chỉ và cặp khóa. Trong kịch bản xác thực phía máy khách, các phần khác nhau của các khóa sẽ được đặt ở đây:

  • Cửa hàng của khách hàng sẽ chứa cặp khóa riêng và chung của khách hàng . Nó được gọi là kho khóa .
  • Các máy chủ lưu trữ 's sẽ chứa của khách hàng công cộng quan trọng. Nó được gọi là cửa hàng ủy thác .

Việc phân tách Truststore và keystore không bắt buộc nhưng được khuyến nghị. Chúng có thể là cùng một tệp vật lý.

Để đặt vị trí hệ thống tệp của hai cửa hàng, hãy sử dụng các thuộc tính hệ thống sau:

-Djavax.net.ssl.keyStore=clientsidestore.jks

và trên máy chủ:

-Djavax.net.ssl.trustStore=serversidestore.jks

Để xuất chứng chỉ của máy khách (khóa chung) sang một tệp, do đó bạn có thể sao chép nó vào máy chủ, sử dụng

keytool -export -alias MYKEY -file publicclientkey.cer -store clientsidestore.jks

Để nhập khóa công khai của máy khách vào kho khóa của máy chủ, hãy sử dụng (như người đăng đã đề cập, việc này đã được quản trị viên máy chủ thực hiện)

keytool -import -file publicclientkey.cer -store serversidestore.jks

Tôi có lẽ nên đề cập rằng tôi không có quyền kiểm soát máy chủ. Các máy chủ đã nhập chứng chỉ công cộng của chúng tôi. Tôi đã được các quản trị viên của hệ thống đó nói rằng tôi cần cung cấp chứng chỉ một cách rõ ràng để có thể gửi nó trong quá trình bắt tay (máy chủ của họ yêu cầu rõ ràng điều này).
tmbrggmn

Bạn sẽ cần khóa công khai và khóa riêng cho chứng chỉ công khai của bạn (cái mà máy chủ biết đến) dưới dạng tệp JKS.
sfussalanger

Cảm ơn mã ví dụ. Trong đoạn mã trên, "mykey-public.cer" chính xác là gì? Đây có phải là chứng chỉ công khai của khách hàng (chúng tôi sử dụng chứng chỉ tự ký)?
tmbrggmn

Đúng vậy, tôi đã đổi tên các tệp trong đoạn mã tương ứng. Tôi hy vọng điều này làm cho nó rõ ràng.
mhaller

Phải, cảm ơn. Tôi tiếp tục bối rối vì rõ ràng "chìa khóa" và "chứng chỉ" được sử dụng thay thế cho nhau.
tmbrggmn

10

Maven pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>some.examples</groupId>
    <artifactId>sslcliauth</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>sslcliauth</name>
    <dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.4</version>
        </dependency>
    </dependencies>
</project>

Mã Java:

package some.examples;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.http.entity.InputStreamEntity;

public class SSLCliAuthExample {

private static final Logger LOG = Logger.getLogger(SSLCliAuthExample.class.getName());

private static final String CA_KEYSTORE_TYPE = KeyStore.getDefaultType(); //"JKS";
private static final String CA_KEYSTORE_PATH = "./cacert.jks";
private static final String CA_KEYSTORE_PASS = "changeit";

private static final String CLIENT_KEYSTORE_TYPE = "PKCS12";
private static final String CLIENT_KEYSTORE_PATH = "./client.p12";
private static final String CLIENT_KEYSTORE_PASS = "changeit";

public static void main(String[] args) throws Exception {
    requestTimestamp();
}

public final static void requestTimestamp() throws Exception {
    SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(
            createSslCustomContext(),
            new String[]{"TLSv1"}, // Allow TLSv1 protocol only
            null,
            SSLConnectionSocketFactory.getDefaultHostnameVerifier());
    try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(csf).build()) {
        HttpPost req = new HttpPost("https://changeit.com/changeit");
        req.setConfig(configureRequest());
        HttpEntity ent = new InputStreamEntity(new FileInputStream("./bytes.bin"));
        req.setEntity(ent);
        try (CloseableHttpResponse response = httpclient.execute(req)) {
            HttpEntity entity = response.getEntity();
            LOG.log(Level.INFO, "*** Reponse status: {0}", response.getStatusLine());
            EntityUtils.consume(entity);
            LOG.log(Level.INFO, "*** Response entity: {0}", entity.toString());
        }
    }
}

public static RequestConfig configureRequest() {
    HttpHost proxy = new HttpHost("changeit.local", 8080, "http");
    RequestConfig config = RequestConfig.custom()
            .setProxy(proxy)
            .build();
    return config;
}

public static SSLContext createSslCustomContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException {
    // Trusted CA keystore
    KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE);
    tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray());

    // Client keystore
    KeyStore cks = KeyStore.getInstance(CLIENT_KEYSTORE_TYPE);
    cks.load(new FileInputStream(CLIENT_KEYSTORE_PATH), CLIENT_KEYSTORE_PASS.toCharArray());

    SSLContext sslcontext = SSLContexts.custom()
            //.loadTrustMaterial(tks, new TrustSelfSignedStrategy()) // use it to customize
            .loadKeyMaterial(cks, CLIENT_KEYSTORE_PASS.toCharArray()) // load client certificate
            .build();
    return sslcontext;
}

}

Nếu bạn muốn có chứng chỉ có sẵn cho tất cả các ứng dụng sử dụng cài đặt JVM cụ thể, thay vào đó hãy làm theo câu trả lời này .
ADTC

là phương pháp configureRequest()để thiết lập proxy của dự án máy khách phải không?
chia sẻ

vâng, đó là cấu hình máy khách http và đó là cấu hình proxy trong trường hợp này
kinjelom

có thể tôi có một câu hỏi ngớ ngẩn, nhưng làm cách nào để tạo một tệp cacert.jks? Tôi có ngoại lệ Ngoại lệ trong luồng "chính" java.io.FileNotFoundException :. \ Caiert.jks (Hệ thống không thể tìm thấy tệp được chỉ định)
Patlatus

6

Đối với những người bạn chỉ muốn thiết lập xác thực hai chiều (chứng chỉ máy chủ và máy khách), sự kết hợp của hai liên kết này sẽ đưa bạn đến đó:

Thiết lập xác thực hai chiều:

https://linuxconfig.org/apache-web-server-ssl-authentication

Bạn không cần phải sử dụng tệp cấu hình openssl mà họ đề cập; chỉ dùng

  • $ openssl genrsa -des3 -out ca.key 4096

  • $ openssl req -new -x509 -ngày 365 -key ca.key -out ca.crt

để tạo chứng chỉ CA của riêng bạn, sau đó tạo và ký các khóa máy chủ và máy khách thông qua:

  • $ openssl genrsa -des3 -out server.key 4096

  • $ openssl req -new -key server.key -out server.csr

  • $ openssl x509 -req -ngày 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 100 -out server.crt

  • $ openssl genrsa -des3 -out client.key 4096

  • $ openssl req -new -key client.key -out client.csr

  • $ openssl x509 -req -ngày 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 101 -out client.crt

Đối với phần còn lại làm theo các bước trong liên kết. Việc quản lý chứng chỉ cho Chrome hoạt động giống như trong ví dụ về firefox được đề cập.

Tiếp theo, thiết lập máy chủ thông qua:

https://www.digitalocean.com/community/tutorials/how-to-create-a-ssl-cert ve-on-apache-for-ub Ubuntu-14-04

Lưu ý rằng bạn đã tạo máy chủ .crt và .key để bạn không phải thực hiện bước đó nữa.


1
Nghĩ rằng bạn có typo trong máy chủ bước thế hệ CSR: nên sử dụng server.keykhôngclient.key
the.Legend

0

Tôi đã kết nối với ngân hàng bằng SSL hai chiều (chứng chỉ máy khách và máy chủ) với Spring Boot. Vì vậy, mô tả ở đây tất cả các bước của tôi, hy vọng nó sẽ giúp được ai đó (giải pháp làm việc đơn giản nhất, tôi đã tìm thấy):

  1. Tạo yêu cầu chứng nhận:

    • Tạo khóa riêng:

      openssl genrsa -des3 -passout pass:MY_PASSWORD -out user.key 2048
    • Tạo yêu cầu chứng chỉ:

      openssl req -new -key user.key -out user.csr -passin pass:MY_PASSWORD

    Giữ user.key(và mật khẩu) và gửi yêu cầu chứng chỉ user.csrđến ngân hàng cho chứng chỉ của tôi

  2. Nhận 2 chứng chỉ: chứng chỉ gốc khách hàng của tôi clientId.crtvà chứng chỉ gốc ngân hàng:bank.crt

  3. Tạo kho khóa Java (nhập mật khẩu khóa và đặt mật khẩu kho khóa):

    openssl pkcs12 -export -in clientId.crt -inkey user.key -out keystore.p12 -name clientId -CAfile ca.crt -caname root

    Đừng chú ý đến đầu ra : unable to write 'random state'. Java PKCS12 keystore.p12đã được tạo.

  4. Thêm vào kho khóa bank.crt(để đơn giản tôi đã sử dụng một kho khóa):

    keytool -import -alias banktestca -file banktestca.crt -keystore keystore.p12 -storepass javaops

    Kiểm tra chứng chỉ kho khóa bằng cách:

    keytool -list -keystore keystore.p12
  5. Sẵn sàng cho mã Java :) Tôi đã sử dụng Spring Boot RestTemplatevới thêm org.apache.httpcomponents.httpcorephụ thuộc:

    @Bean("sslRestTemplate")
    public RestTemplate sslRestTemplate() throws Exception {
      char[] storePassword = appProperties.getSslStorePassword().toCharArray();
      URL keyStore = new URL(appProperties.getSslStore());
    
      SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(keyStore, storePassword)
      // use storePassword twice (with key password do not work)!!
            .loadKeyMaterial(keyStore, storePassword, storePassword) 
            .build();
    
      // Solve "Certificate doesn't match any of the subject alternative names"
      SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
    
      CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
      HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(client);
      RestTemplate restTemplate = new RestTemplate(factory);
      // restTemplate.setMessageConverters(List.of(new Jaxb2RootElementHttpMessageConverter()));
      return restTemplate;
    }

Bạn có thể làm tất cả với keytool. Không cần forOpenSSL trong việc này cả.
Hầu tước Lorne

0

Cho một tệp p12 có cả chứng chỉ và khóa riêng (ví dụ được tạo bởi openssl), đoạn mã sau sẽ sử dụng mã đó cho một kết nối HttpsURLC cụ thể:

    KeyStore keyStore = KeyStore.getInstance("pkcs12");
    keyStore.load(new FileInputStream(keyStorePath), keystorePassword.toCharArray());
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(keyStore, keystorePassword.toCharArray());
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(kmf.getKeyManagers(), null, null);
    SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();

    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
    connection.setSSLSocketFactory(sslSocketFactory);

Các SSLContextmất một thời gian để khởi tạo, vì vậy bạn có thể muốn cache nó.


-1

Tôi nghĩ rằng sửa chữa ở đây là loại kho khóa, pkcs12 (pfx) luôn có khóa riêng và loại JKS có thể tồn tại mà không cần khóa riêng. Trừ khi bạn chỉ định trong mã của mình hoặc chọn trình duyệt thông qua chứng chỉ, máy chủ không có cách nào để biết nó đại diện cho máy khách ở đầu bên kia.


1
Theo truyền thống, định dạng PKCS12 được sử dụng cho privatekey-AND-cert, nhưng Java kể từ 8 năm 2014 (hơn một năm trước câu trả lời này) đã hỗ trợ PKCS12 có chứa cert mà không có privatekey (s). Bất kể định dạng kho khóa, máy khách xác thực đều yêu cầu privatekey-AND-cert. Tôi không hiểu câu thứ hai của bạn, nhưng máy khách Java có thể tự động chọn chứng chỉ và khóa khách hàng nếu có ít nhất một mục phù hợp có sẵn hoặc một trình điều khiển khóa có thể được cấu hình để sử dụng một mục được chỉ định.
dave_thndry_085

Câu thứ hai của bạn là hoàn toàn không chính xác. Máy chủ cung cấp người ký đáng tin cậy và khách hàng sẽ chết hoặc không cung cấp chứng chỉ bảo vệ ràng buộc đó. Tự động, không thông qua 'trong mã của bạn'. Đó 'cách nhận biết của máy chủ' đại diện cho khách hàng '.
Hầu tước Lorne
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.