2010-02-10 27 views
19

Actualmente, he implementado con éxito la seguridad de Autenticación mutua siempre que el cliente acceda al sitio web utilizando un navegador web, ya que los navegadores se encargan de todo el intercambio de certificados para usted. Ahora necesito crear una interfaz segura con la que los usuarios puedan acceder a los servicios web a través de HTTPS, utilizando la autenticación mutua requerida por el servidor.Autenticación mutua con servicios web

En primer lugar, ¿hay algún recurso que nadie sepa que pueda ayudarme con esto? He buscado bastante tiempo y no encontré nada. ¿Algún otro consejo que alguien pueda darme sobre cómo hacer esto?

En segundo lugar, creo que mi mayor obstáculo es mi falta de comprensión sobre cómo manejar los certificados. ¿Cómo negoció la aceptación de la clave del servidor y la presentación de mi propia clave para el servidor? Esto está en Java.

Respuesta

1

Una receta simple se da en this blog entry.

Pero creo que la respuesta real puede depender de las API de Java que esté utilizando para implementar las interacciones HTTP del lado del cliente. Por ejemplo, parece que harías las cosas a bit differently usando JAX-RPC.

6

Si la biblioteca del servicio web utiliza la clase estándar java.net.URL como cliente HTTP, puede establecer algunos system properties y la autenticación bidireccional se gestionará mediante el soporte HTTPS incorporado.

El necessary properties son:

  • javax.net.ssl.trustStore: Contiene certificados de CA raíz
  • javax.net.ssl.keyStore: Contiene certificado de cliente y clave secreta
  • javax.net.ssl.keyStorePassword: La contraseña de protección de clave privada

Estos cliente la configuración se convierte en la predeterminada para todas las conexiones SSL por el proceso. Si desea un control más preciso, debe configurar su propio SSLContext. Si eso es posible con el tiempo de ejecución de tu servicio web depende del tiempo de ejecución que hayas elegido.

11

Para la autenticación mutua con SSL (también conocido como de doble vía SSL) fuera de un navegador, tendrá que ... Bueno, en realidad, vamos a ver lo que necesita para una sola vía SSL primera:

  1. Un almacén de claves
  2. servidor Un cliente de almacenamiento de confianza

el almacén de claves del servidor contiene el certificado (posiblemente autofirmado) del servidor y la clave privada. El servidor utiliza esta tienda para firmar mensajes y devolver credenciales al cliente.

El almacén de confianza del cliente contiene el certificado del servidor (autofirmado) (extraído del almacén de claves del servidor en un certificado independiente, sin la clave privada del servidor). Esto es necesario si el certificado no está firmado por una CA confiable para la cual ya tiene un certificado en el almacén de confianza incluido con el JRE. Este paso permite crear una cadena de confianza.

Con esto, puede implementar SSL unidireccional (el caso de uso tradicional).

Para implementar SSL de dos vías, es necesario realizar esta configuración "simétrica", por lo que tendremos que añadir:

  1. Un almacén de claves del cliente
  2. Un servidor de almacenamiento de confianza

El El almacén de claves del cliente contiene el certificado del cliente (posiblemente autofirmado) y la clave privada. El cliente utiliza esta tienda con el mismo propósito que el almacén de claves del servidor, es decir, para enviar credenciales de cliente al servidor durante el protocolo de enlace mutuo de autenticación TLS.

El almacén de confianza del servidor contiene los certificados autónomos de los clientes (autofirmados) (extraídos del almacén de claves de los clientes en certificados independientes, sin la clave privada del cliente). Esto es necesario por los mismos motivos que se mencionaron anteriormente.

Algunos recursos para ayudar a generar todas estas cosas y para poner en práctica las soluciones finales:

+3

A pesar de que he explicado el concepto de autenticación mutua bastante bien, los enlaces no son muy útiles en absoluto. ¡La seguridad del servicio web Java ha cambiado bastante desde 2006! :) – Catchwa

14

Pasé mucho tiempo en esto, pero finalmente encontré un ejemplo que actu aliado funciona. Está basado en Glassfish y Netbeans, pero supongo que podrías hacerlo funcionar en otros entornos (por ejemplo, Eclipse y Tomcat) si jugaste con él.

http://java.sun.com/webservices/reference/tutorials/wsit/doc/WSIT_Security9.html#wp162511

El problema que he encontrado es sin embargo cuando se quiere usar sus propios certificados, no los que vienen pre-instalado con glassfish.

Nota: No soy un experto en seguridad. ¡No implemente esto en un entorno de producción!

para hacer esto que estoy usando NetBeans 6.9, JDK 1.6, GlassFish 3.0.1 y v1.0 OpenSSL (estoy usando los binarios de Win32 no oficiales)

# Create the CA 
mkdir ca server client 
cd ca 
openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.pem 
echo 02 > serial.txt 
cd .. 

# Creating the Server Keystore 

openssl req -days 3650 -newkey rsa:1024 -keyout server/server.key -out server/server.req 
openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in server/server.req -out server/server.crt 
openssl pkcs12 -export -inkey server/server.key -in server/server.crt -out server/server.p12 -name server 
keytool -importkeystore -destkeystore server/server.jks -deststoretype jks -srckeystore server/server.p12 -srcstoretype pkcs12 
keytool -exportcert -alias server -keystore server/server.jks -file server/server.cer 

# Create the Client Keystore 

openssl req -days 3650 -newkey rsa:1024 -keyout client/client1.key -out client/client1.req 
openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in client/client1.req -out client/client1.crt 
openssl pkcs12 -export -inkey client/client1.key -in client/client1.crt -out client/client1.p12 -name client1 
keytool -importkeystore -destkeystore client/client1.jks -deststoretype jks -srckeystore client/client1.p12 -srcstoretype pkcs12 
keytool -exportcert -alias client1 -keystore client/client1.jks -file client/client1.cer 

# Import public keys and certificates into each others keystores 

keytool -import -noprompt -trustcacerts -alias client1 -file client/client1.cer -keystore server/server.jks 
keytool -import -noprompt -trustcacerts -alias server -file server/server.cer -keystore client/client1.jks 
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore server/server.jks 
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore client/client1.jks 
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\cacerts.jks" 
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\Java\jdk1.6\jre\lib\security\cacerts" 
move "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks" "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks.backup" 
copy server\server.jks "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks" 

En la consola de administración de GlassFish, habilite Seguridad en su oyente http, marque las casillas SSL3, TLS y Autenticación de cliente, configure Nickname del certificado en el servidor, Key Store en config \ keystore.jks, Trust Store en config \ keystore.jks, Trust Algorithm en PKIX y deje la Longitud máxima del certificado en 5.

En NetBeans, cree un nuevo proyecto de aplicación web. Dentro de eso, crea un nuevo servicio web.

Mi código de servicio Web se veía así:

@WebService() 
public class ListProducts { 

    @Resource WebServiceContext context; 

    @WebMethod(operationName = "listProducts") 
    public String listProducts() { 
    return context.getUserPrincipal().toString(); 
    } 

} 

Haga clic derecho sobre el servicio web y seleccionar Servicio Web Editar atributos. Marque la casilla Servicio seguro y seleccione Seguridad de certificados mutuos como el Mecanismo de seguridad. Haga clic en el botón Configurar ... y marque la casilla Cifrar firma. Ahora desmarque la casilla Usar valores predeterminados de desarrollo y luego haga clic en el botón Almacén de claves. Establezca la ubicación de su servidor de claves server.jks y seleccione el alias server.Haz lo mismo para la configuración de Truststore (aunque no tienes que seleccionar un alias aquí).

Importe el certificado del cliente client1.p12 a su navegador. Implemente su servicio web a Glassfish. Abra su servicio web en un navegador y busque el WSDL implementado a través de HTTPS. Descargue el WSDL y cualquier otro esquema. Cambie el nombre de cualquier esquema referenciado a copias locales para que cuando use WSDL2Java NetBeans no use ningún recurso remoto. (Este párrafo se debe a que ha restringido su WSDL a clientes con un certificado aprobado, pero NetBeans no puede recuperarlo de forma remota porque no tiene acceso al certificado en cuestión).

Cree un nuevo proyecto de Java. Crea un nuevo cliente de servicio web. Cuando se le solicite, señale NetBeans en su archivo WSDL guardado. Importe los archivos de la biblioteca METRO2.0 (C:\Program Files\Netbeans 6.9\enterprise\modules\ext\metr\webservices-*.jar). Mi código se veía así:

public static void main(String[] args) { 
    System.getProperties().put("javax.net.ssl.keyStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks"); 
    System.getProperties().put("javax.net.ssl.keyStorePassword", "changeit"); 
    System.getProperties().put("javax.net.ssl.trustStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks"); 
    System.getProperties().put("javax.net.ssl.trustStorePassword", "changeit"); 
    System.out.println(new ListProductsService().getListProductsPort().listProducts()); 
} 

Copia webservices-api.jar en su Java \ jdk1.6 \ jre \ lib \ directorio respaldado. Haga clic con el botón derecho en la referencia del servicio web y seleccione Editar atributos del servicio web. Establezca la ubicación del almacén de claves en client1.jks y configure el alias en client1. Establezca la ubicación del almacén de confianza en client1.jks y establezca el alias en server.

Esperamos que usted puede ahora ejecutar su cliente y debería ver una salida de este modo: [email protected], CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US

Cuestiones relacionadas