2012-06-07 14 views
16

Necesitamos implementar SSL bidireccional en Google App Engine, donde enviamos solicitudes de servicios web utilizando JAX-WS a un servidor que requiere autenticación SSL de 2 vías.SSL bidireccional para servicios web en GAE (java)

¿Cómo podemos configurar SSL bidireccional para nuestras solicitudes de servicios web salientes?

Sabemos que javax.net.ssl* está prohibido en el entorno de App Engine.

He aquí un ejemplo de nuestro código:

@WebService(name="ListenerSoap", targetNamespace = "http://example.com/Listener.Wsdl") 
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) 
public interface ListenerSoap { 

    @WebMethod(operationName = "Ping", action="http://example.com/Listener.Wsdl#Ping") 
    public void ping(); 
} 

@WebServiceClient(name="Listener", targetNamespace="http://example.com/Listener.Wsdl", wsdlLocation = "https://example.com/Listener.asmx?WSDL") 
public class Listener extends Service 
{ 
    public ListenerSoap getListenerSoap() { 
    return super.getPort(new QName("http://example.com/Listener.Wsdl", 
         "ListenerSoap"), ListenerSoap.class); 
    } 
} 

Y un ejemplo de código anterior en uso:

ListenerSoap soap = new Listener().getListenerSoap(); 
soap.ping(); 

Calculo que podemos almacenar los almacenes de claves o cualquier certs necesarios la DataStore como objetos binarios (aunque la forma de cargarlos sigue siendo un poco vaga para mí).

¿Cómo podemos hacer para establecer los valores necesarios necesarios para que este servicio web se autentique mediante SSL bidireccional?

Gracias por cualquier ayuda

Actualización:

través de la investigación que he visto esta es la forma en que se puede hacer en un servidor tradicional (uno con acceso de sistema de archivos):

ListenerSoap soap = new Listener().getListenerSoap(); 
((BindingProvider) soap).getRequestContext().put("javax.net.ssl.keyStore", "client_cert.p12" 

Sin embargo, en este enfoque, se espera que client_cert.p12 esté en el sistema de archivos.

Además, SSLSocketFactory, SSLContext, KeyManager y KeyManagerFactory no están permitidos en GAE.

Actualización:

A partir del GAE SDK versión 1.7.7. esto debería ser posible ahora:

Similarly, Java developers can now use the javax.net.ssl package to make outbound SSL connections. 

GAE 1.7.7 SDK Release Notes

+6

Hay una solicitud de función abierta para admitir certificados de cliente en el servicio URLFetch: http://code.google.com/p/googleappengine/issues/detail?id=3719 –

Respuesta

0

Por lo que sé de dos SSL manera, usted no tendrá ningún vínculo con el código Java EE: dos vías SSL es una seguridad de capa de transporte: cuando la aplicación cliente intentará crear una conexión HTTP segura (HTTPS) con el servicio, el servidor solicitará un certificado y aprobará o no este certificado. Si se aprueba el certificado del cliente, se establecerá una conexión segura entre las partes y se les permitirá intercambiar algunos mensajes a través de este túnel. Pero este proceso se realiza en la capa de transporte. Su código (en la capa de aplicación) nunca será informado de este proceso. Para establecer un SSL de dos vías, la configuración se realiza en la configuración del servidor de aplicaciones para el puerto SSL.

+4

Esto no es absolutamente cierto. Es completamente posible establecer una conexión SSL bidireccional a través del código de la aplicación, como por ejemplo establecer 'systemProps.put (" javax.net.ssl.keyStore ", keyStorePath);' por ejemplo. El problema es GAE listas negras de los paquetes 'java.net.ssl ​​*' y por lo tanto es imposible hacer esto en GAE en el momento de la escritura por este motivo. – Cuga

+0

debería admitir que estaba equivocado. Aquí un código de ejemplo sobre cómo implementar SSL bidireccional en un código java: https://sites.google.com/site/ssljavaguide/example-code/2-way-ssl – omartin

+0

Eso todavía no funcionará en GAE porque todos las clases están en la lista negra bajo los paquetes 'javax.net.ssl. *', incluyendo 'SSLSocket' y' SSLSocketFactory' – Cuga

1
ListenerSoap soap = new Listener().getListenerSoap(); 

espero que mejora

Gracias

+0

Sí, incluso está incluido en la publicación ... la pregunta es cómo obtener SSL bidireccional trabajando en GAE- - una tarea que parece no-factible. – Cuga

1

Sé que usted podría no querer escuchar esto, pero utilizando SSL es caro y problemático para la comunicación bidireccional.Dependiendo de la cantidad de control que tenga sobre los extremos del servidor/cliente, prefiero un conducto bidireccional simple como sockets web y un protocolo de paquete de datos que simplemente puede implementar AES. Realmente depende del problema que intentas resolver.

+2

Creo que OP está hablando de una autorización * bidireccional (autenticación, en realidad). –

+0

y una vez autenticado? –

+1

La * comunicación * es segura en ambas direcciones; las claves pública/privada se utilizan para intercambiar claves simétricas que ambas partes utilizan para el cifrado. Esta pregunta se trata de usar un certificado en * ambos * el servidor * y * servidor, para autenticar cada uno al otro. –

1

Parece que hay confusión sobre la conexión simple a través de SSL (https://...) y lo que se conoce como "autenticación mutua" o "infraestructura de clave pública (PKI)". En realidad puedes hacer ambas cosas o una independientemente de otra. Con este último (a lo que creo que se refiere la pregunta original), cuando realiza una solicitud al servidor, el servidor responderá pidiéndole un certificado que debe presentar para autenticarse.

Para responder a la pregunta específica por encima de (carga de un almacén de claves a partir de datos binarios), no creo que esto es realmente posible, ya que es el tiempo de ejecución de Java que recoge en su almacén de claves. Lo único que puedes hacer es cargar los bits de tu almacén de datos y escribirlos temporalmente en el disco. Opcionalmente elimínelo cuando la aplicación exista. Esto lo he hecho antes y funciona bastante bien. Si hace esto, le recomiendo usar una ubicación probable que sea modificable (como System.getProperty("java.io.tmpdir"));), a continuación, después de escribir el archivo en disco, establezca las propiedades de JVM (por ejemplo System.getProperties().put("javax.net.ssl.keyStore","...");)

+0

La otra opción (si no puedes escribir en el disco ni usar javax.net.ssl. *) es hacer la conexión manualmente (es decir, usando Apache HTTP Client), para agregar un almacén de claves Luego, simplemente pasará a HTTP POST normal al punto final y analizará la respuesta. Ver: http://stackoverflow.com/questions/5206010/using-apache-httpclient-for-https –

+0

Como se menciona en la actualización de la publicación original, no es posible establecer 'javax.net.ssl' en GAE debido a una lista negra de esos paquetes. Tampoco es posible escribir en ningún disco de archivo. Hemos configurado PKI en otros servidores usando eso, pero GAE no lo permitirá. – Cuga

+0

Lo tengo. No estoy familiarizado con GAE. Parece que su única opción es no usar el código JAX-WS, en lugar de utilizar algo un nivel más bajo como Apache HTTPClient donde puede establecer toda esa información de seguridad. No es bonito, pero he usado algo como Velocity para crear un mensaje SOAP y usar Apache HC para enviarlo al servidor. Lo malo es que tienes que analizar la respuesta manualmente (sin una elegante asignación de POJO que obtendrías con el código generado por JAX-WS). –

2

Desde mi conocimiento limitado acerca de la autorización SSL, parece que puede estar perdiendo algo de vital importancia aquí; los certificados. El SSL bidireccional requiere que los certificados del cliente y del servidor estén en su almacén de claves, que puede ser un certificado autofirmado (un archivo pkcs12 o pem, que puede generar fácilmente con algunos comandos a través de shell) o un certificado propietario emitido por una compañía autorizada como Thawte o Verisign. Aunque no estoy seguro de si ese es el problema al que se enfrenta, pero es bueno comprobarlo. (Además, soy novato así que por favor no degrade mi respuesta, solo intento sugerir posibles opciones.)

+1

Gracias. Tenemos todas las llaves y certificados. El problema era poder proporcionar los certificados en el entorno de GAE, que no era posible en ese momento, pero hoy parece que sería posible con las recientes listas blancas por parte de Google. – Cuga

1

SSL de 2 vías (desde una aplicación alojada en GAE al mundo exterior) no es compatible hasta donde yo saber. Intenté una aplicación de muestra hace unos meses y me sentí frustrado al descubrir que GAE ni siquiera admite esta característica básica ... y la documentación tampoco está clara. No podrá presentar el certificado del cliente cuando se contacte con un servicio web. No hay lugar para almacenarlo, no se puede acceder al almacén de claves.

+0

No lo he probado aún, pero a partir de GAE SDK v1.7.7 podría ser posible hacer esto ahora, ya que han incluido en la lista blanca los paquetes 'javax.net.ssl', lo que ahora debería permitirnos especificar el certificado a través de '((BindingProvider) soap) .getRequestContext(). Put (" javax.net.ssl.keyStore "...' – Cuga

Cuestiones relacionadas