Soy un nuevo usuario de los servicios REST. Necesito consumir un servicio RESTful API generado con Jersey. El problema surge porque ese servicio está alojado en un host remoto y requiere acceso https con el certificado.Consumo de servicio RESTful sobre https con certficate usando Java
Obtuve mi certificado de la organización y puedo acceder al servicio REST API con cualquiera de mis navegadores (con certificado establecido en ellos).
He leído gran cantidad de puestos de aquí, y yo he seguido la respuesta en este tema: Using HTTPS with REST in Java
Ahora he mi configuración de certificados en mi almacén de claves Java. Pero no sé cómo usar eso en mi programa Java para que use exactamente el certificado que necesito para hacer la conexión https.
Este es mi código de conexión simple para las pruebas locales.
package rest.test.first;
import java.net.URI;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
public class TestClient{
public static void main(String[]args){
ClientConfig config= new DefaultClientConfig();
Client client=Client.create(config);
WebResource service=client.resource(getBaseURI());
//Fluentinterfaces
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_PLAIN).get(ClientResponse.class).toString());
//Getplaintext
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_PLAIN).get(String.class));
//GetXML
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_XML).get(String.class));
//TheHTML
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_HTML).get(String.class));
}
private static URI getBaseURI(){
return UriBuilder.fromUri("http://localhost:8080/rest.test").build();
}
}
Me'v leer sobre el uso de propiedades del conjunto del sistema para especificar la ruta a keystore con este código:
System.setProperty("javax.net.ssl.keyStore", "/path/to/keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
todavía tengo 401 Error en la conexión con el servidor remoto.
Pero entonces no sé cómo hacer la conexión SSL usando mi certificado en el almacén de claves. También he estado leyendo sobre el uso de SSLSocketFactory para este propósito, pero no pude hacer que funcione como se explica en este post: How can I use different certificates on specific connections?
He conseguido recuperar mi certificado de almacén de claves con este código .. ahora sólo necesita saber cómo usarlo en la conexión:
package rest.test.first;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
public class keystore {
public static void main(String[] args) throws Exception {
String keystoreFilename = "/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts";
char[] password = "changeit".toCharArray();
String alias = "remote_https_server";
FileInputStream fIn = new FileInputStream(keystoreFilename);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(fIn, password);
Certificate cert = keystore.getCertificate(alias);
System.out.println(cert);
}
}
Ok, esa es la última secuencia de comandos que he escrito. Puedo conectarme a sitios https pero aún no puedo conectarme a los sitios https que requieren enviar mi certificado para autenticarse.
package rest.test.first;
import java.io.*;
import java.net.*;
import java.security.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class urlConnection{
public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.trustStore", "/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
//TrustStore..
char[] passphrase = "changeit".toCharArray(); //password
KeyStore keystore = KeyStore.getInstance("JKS");
//KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(new FileInputStream("/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts"), passphrase); //path
//TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); //instance
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);
SSLContext context = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = tmf.getTrustManagers();
context.init(null, trustManagers, null);
SSLSocketFactory sf = context.getSocketFactory();
URL url = new URL("https://www.google.es");
HttpsURLConnection httpsCon = (HttpsURLConnection) url.openConnection();
httpsCon.setSSLSocketFactory(sf);
httpsCon.setRequestMethod("GET");
/*InputStream inStrm = httpsCon.getInputStream();
System.out.println("\nContent at " + url);
int ch;
while (((ch = inStrm.read()) != -1)){
System.out.print((char) ch);
inStrm.close();
}*/
System.out.println("Response Message is " + httpsCon.getResponseMessage());
}
}
¿Cómo generó su almacén de claves? En el código que publicaste, ¿por qué estás usando el almacén de confianza 'cacerts'? Sugeriría importar su certificado en su propio JKS y usarlo en la llamada a 'System.setProperty (" javax.net.ssl.keyStore "," ... ")'. – poida