httppost - httpclient java ejemplo
¿Cómo uso una URL HTTPS local en Java? (6)
El problema por el que se queja es que cuando crea una conexión SSL, el servidor debe presentar un certificado válido al cliente. Puede escribir un punto final apropiado en Java (HTTPServerSocket lo hará, creo) pero requeriría algunos hackers para configurarlo. Probablemente sea más fácil configurar un servidor web local con cualquier cosa que maneje SSL correctamente (Apache, lighttp, lo que sea) y cree un certificado autofirmado utilizando las herramientas de openssl.
ActualizadoAquí hay un ejemplo del Almanaque de Java. http://www.exampledepot.com/egs/javax.net.ssl/Server.html
Un socket de servidor SSL requiere certificados que enviará a los clientes para la autenticación. Los certificados deben estar contenidos en un almacén de claves cuya ubicación debe especificarse explícitamente (no hay un valor predeterminado). Siguiendo el ejemplo, describimos cómo crear y especificar un almacén de claves para que el socket del servidor SSL lo use.
try {
int port = 443;
ServerSocketFactory ssocketFactory = SSLServerSocketFactory.getDefault();
ServerSocket ssocket = ssocketFactory.createServerSocket(port);
// Listen for connections
Socket socket = ssocket.accept();
// Create streams to securely send and receive data to the client
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
// Read from in and write to out...
// Close the socket
in.close();
out.close();
} catch(IOException e) {
}
Especifique el almacén de claves de certificados utilizando la propiedad del sistema javax.net.ssl.keyStore:
> java -Djavax.net.ssl.keyStore=mySrvKeystore -Djavax.net.ssl.keyStorePassword=123456 MyServer
Utilizando la clase URL de Java, puedo conectarme a un servidor HTTPS
externo (como nuestro sitio de producción), pero al usar una URL local obtengo la siguiente excepción.
"SunCertPathBuilderException: unable to find valid certification path to requested target".
¿Cómo obtengo una ruta de certificación válida?
EDITAR: No estoy usando esta URL para crear una conexión directamente, estoy pasando la URL a un itext
PDFReader
, que luego está teniendo el problema de conexión.
Otra cosa para mirar es el TrustManager
que está usando. El mensaje de error sugiere que el certificado presentado por el servidor no está firmado por una raíz de confianza. Como no tiene control directo sobre el socket SSL que se crea, creo que su mejor SSLContext
es inicializar su propio SSLContext
con un TrustManager
que se haya configurado con la CA raíz de la cadena de certificados del servidor. Luego configure este contexto como el predeterminado .
Esto supone que está utilizando Java 6. La API es más limitada en Java 5. Puede obtener una SSLSocketFactory
predeterminada, pero no hay una forma estándar de configurarla.
Probablemente necesites configurar un HostnameVerifier
. Antes de conectarse, debe agregarlo al objeto de conexión
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
// check hostname/session
return true;
}
});
conn.connect();
// read/write...
Sin duda hay algunas implementaciones, si necesita una. Es posible que también desee ver el proyecto HttpClient .
Aquí estaba mi solución que incorpora algunas de las ideas en este hilo y peiced junto con el código de alrededor de la red. Todo lo que llamo esta función y establece el administrador de confianza predeterminado y el verificador de nombre de host para HttpsURLConnection. Esto puede ser indeseable para algunos porque afectará a todas las HttpsURLConnections, pero solo estoy escribiendo un proxy simple, así que funcionó para mí.
private void setTrustAllCerts() throws Exception
{
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType ) { }
public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType ) { }
}
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance( "SSL" );
sc.init( null, trustAllCerts, new java.security.SecureRandom() );
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(
new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
});
}
catch ( Exception e ) {
//We can not recover from this exception.
e.printStackTrace();
}
}
También puede ayudarlo a agregar el certificado de que el servidor localhost está usando (supongo que está autofirmado) en el almacén de claves de la JVM, utilizando la utilidad "keytool" . Esto debería tener el efecto de decirle a la JVM "puede confiar en este certificado".
Terminé ejecutando un método estático (solo en dev) que instala un TrustManager muy confiable (lo acepta todo) y también agrega un nombre de servidor que siempre se devuelve verdadero (gracias a sblundy ).