Indagamos por diferentes espacios para brindarte la respuesta para tu inquietud, si tienes alguna difcultad deja tu comentario y responderemos con mucho gusto.
Solución:
Creo que la principal diferencia es que en Java, normalmente pones el key y el certificado a un key guárdelo y utilícelo desde allí. Como mencionas a menudo, las personas quieren usar una biblioteca separada para ello, como el cliente httpcomponents mencionado (al igual que estás usando la biblioteca de solicitudes en tu ejemplo de Python).
A continuación, se muestra un ejemplo del uso de un certificado de cliente de key store, utilizando la biblioteca mencionada anteriormente:
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.security.KeyStore;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class MyClientCertTest
private static final String KEYSTOREPATH = "/clientkeystore.jks"; // or .p12
private static final String KEYSTOREPASS = "keystorepass";
private static final String KEYPASS = "keypass";
KeyStore readStore() throws Exception
try (InputStream keyStoreStream = this.getClass().getResourceAsStream(KEYSTOREPATH))
KeyStore keyStore = KeyStore.getInstance("JKS"); // or "PKCS12"
keyStore.load(keyStoreStream, KEYSTOREPASS.toCharArray());
return keyStore;
@Test
public void readKeyStore() throws Exception
assertNotNull(readStore());
@Test
public void performClientRequest() throws Exception
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(readStore(), KEYPASS.toCharArray()) // use null as second param if you don't have a separate key password
.build();
HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpResponse response = httpClient.execute(new HttpGet("https://slsh.iki.fi/client-certificate/protected/"));
assertEquals(200, response.getStatusLine().getStatusCode());
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
EntityUtils.consume(entity);
Maven pom para versiones de dependencia:
4.0.0
com.acme
httptests
0.0.1-SNAPSHOT
1.8
1.8
org.apache.httpcomponents
httpclient
4.5.3
junit
junit
4.12
test
org.apache.maven.plugins
maven-surefire-plugin
2.9
-Djavax.net.debug=all
También publiqué una página de prueba simple para probar un certificado de cliente.
Solo para demostrar que se puede hacer, a continuación se muestra un ejemplo de cómo usar un certificado de cliente simplemente usando la API estándar de Java, sin bibliotecas adicionales.
import org.junit.Test;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyStore;
public class PlainJavaHTTPS2Test
@Test
public void testJKSKeyStore() throws Exception
final String KEYSTOREPATH = "clientkeystore.jks";
final char[] KEYSTOREPASS = "keystorepass".toCharArray();
final char[] KEYPASS = "keypass".toCharArray();
try (InputStream storeStream = this.getClass().getResourceAsStream(KEYSTOREPATH))
setSSLFactories(storeStream, "JKS", KEYSTOREPASS, KEYPASS);
testPlainJavaHTTPS();
@Test
public void testP12KeyStore() throws Exception
final String KEYSTOREPATH = "clientkeystore.p12";
final char[] KEYSTOREPASS = "keystorepass".toCharArray();
final char[] KEYPASS = "keypass".toCharArray();
try (InputStream storeStream = this.getClass().getResourceAsStream(KEYSTOREPATH))
setSSLFactories(storeStream, "PKCS12", KEYSTOREPASS, KEYPASS);
testPlainJavaHTTPS();
private static void setSSLFactories(InputStream keyStream, String keystoreType, char[] keyStorePassword, char[] keyPassword) throws Exception
KeyStore keyStore = KeyStore.getInstance(keystoreType);
keyStore.load(keyStream, keyStorePassword);
KeyManagerFactory keyFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, keyPassword);
KeyManager[] keyManagers = keyFactory.getKeyManagers();
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagers, null, null);
SSLContext.setDefault(sslContext);
public void testPlainJavaHTTPS() throws Exception
String httpsURL = "https://slsh.iki.fi/client-certificate/protected/";
URL myUrl = new URL(httpsURL);
HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection();
try (InputStream is = conn.getInputStream())
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String inputLine;
while ((inputLine = br.readLine()) != null)
System.out.println(inputLine);
Y aquí hay una tercera versión con la menor cantidad de código, pero que se basa en el hecho de que a) el almacén de claves es un archivo en el disco, no dentro de jar, yb) key contraseña debe ser idéntica a la contraseña del almacén de claves.
import org.junit.BeforeClass;
import org.junit.Test;
import java.net.URL;
import java.io.*;
import javax.net.ssl.HttpsURLConnection;
public class PlainJavaHTTPSTest
@BeforeClass
public static void setUp()
System.setProperty("javax.net.ssl.keyStore", "/full/path/to/clientkeystore-samepassword.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "keystorepass");
@Test
public void testPlainJavaHTTPS() throws Exception
String httpsURL = "https://slsh.iki.fi/client-certificate/protected/";
URL myUrl = new URL(httpsURL);
HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection();
try (InputStream is = conn.getInputStream())
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String inputLine;
while ((inputLine = br.readLine()) != null)
System.out.println(inputLine);
Por supuesto, las propiedades establecidas anteriormente en el código también se pueden proporcionar como parámetros de inicio, -Djavax.net.ssl.keyStore=/full/path/to/clientkeystore-samepassword.jks
y -Djavax.net.ssl.keyStorePassword=keystorepass
.
Si desea utilizar el cliente HTTP Apache en lugar del cliente HTTP Java, debe proporcionar a SSLFactory su almacén de claves y configurar DefaultHTTPClient para utilizarlo en el protocolo HTTPS.
Puede encontrar un ejemplo práctico aquí.
Espero que eso ayude.
Reseñas y valoraciones del artículo
Si para ti ha sido de provecho este post, sería de mucha ayuda si lo compartes con el resto entusiastas de la programación y nos ayudes a difundir esta información.