springboot certificado cert java ssl spring-security spring-boot tomcat8

java - certificado - Implementación de SSL de 2 vías con arranque de resorte



spring boot use ssl (2)

Puede configurar clientAuth=want , ver Apache Tomcat 8 Configuration Reference :

Establézcalo en true si desea que la pila SSL requiera una cadena de certificados válida del cliente antes de aceptar una conexión. Establézcalo para que want si la pila SSL solicita un Certificado de cliente, pero no falla si no se presenta uno. Un valor false (que es el valor predeterminado) no requerirá una cadena de certificados a menos que el cliente solicite un recurso protegido por una restricción de seguridad que utilice la autenticación CLIENT-CERT .

y luego lea el certificado del cliente con Spring Security - Autenticación X.509 :

También puede usar SSL con "autenticación mutua"; el servidor luego solicitará un certificado válido del cliente como parte del protocolo de enlace SSL. El servidor autenticará al cliente al verificar que su certificado esté firmado por una autoridad aceptable. Si se ha proporcionado un certificado válido, se puede obtener a través de la API de servlet en una aplicación. El módulo Spring Security X.509 extrae el certificado utilizando un filtro. Correlaciona el certificado con un usuario de la aplicación y carga el conjunto de autoridades otorgadas por ese usuario para usar con la infraestructura estándar de Spring Security.

y

clientAuth también se puede configurar como clientAuth si aún desea que las conexiones SSL tengan éxito incluso si el cliente no proporciona un certificado. Los clientes que no presenten un certificado no podrán acceder a ningún objeto protegido por Spring Security a menos que utilicen un mecanismo de autenticación que no sea X.509, como la autenticación de formularios.

Estoy creando algunos servicios web relajantes y estoy usando Spring-Boot para crear un contenedor de tomcat integrado.

Uno de los requisitos es que esto implemente SSL de 2 vías. He estado mirando el objeto HttpSecurity y puedo conseguir que ejecute solo los servicios web a través de un canal SSL usando esto: -

@Override protected void configure(HttpSecurity http) throws Exception { System.out.println("CONFIGURED"); http // ... .requiresChannel() .anyRequest().requiresSecure(); }

Lo que parece que no encuentro es una forma de hacer que el servicio web solo sea accesible para las aplicaciones que proporcionan un certificado de cliente válido.

Solo tengo un conocimiento básico de SSL por lo que incluso un puntero general en la dirección correcta sería apreciado.

El servidor en el que se está implementando tendrá una combinación de aplicaciones: este es el único que debe bloquearse con SSL bidireccional. Lo que realmente estoy buscando es una forma de bloquear una sola aplicación para que solo acepte certificados de clientes.


Me encontré con un problema similar y pensé que compartiría la solución con la que vine.

En primer lugar, debe comprender que la autenticación del certificado SSL se manejará en el lado del servidor web (explicación de cfr. Dur, con la configuración "clientAuth = want"). Luego, su aplicación web debe configurarse para manejar el certificado proporcionado (y permitido), asignarlo a un usuario, etc.

La pequeña diferencia que tengo contigo es que estoy empaquetando mi aplicación de inicio de primavera en un archivo WAR, que luego se implementa en un servidor de aplicaciones Tomcat existente.

El archivo de configuración server.xml de mi Tomcat define un conector HTTPS de la siguiente manera:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" keystoreFile="/opt/tomcat/conf/key-stores/ssl-keystore.jks" keystorePass=“some-complex-password“ clientAuth="want" sslProtocol="TLS" truststoreFile="/opt/tomcat/conf/trust-stores/ssl-truststore.jks" truststorePass=“some-other-complex-password” />

Pequeño comentario para evitar confusiones: keystoreFile contiene el par certificado / clave privada utilizado para SSL (solo), mientras que truststoreFile contiene los certificados de CA permitidos para la autenticación SSL del cliente (tenga en cuenta que también puede agregar los certificados del cliente directamente en ese trust-store) .

Si está utilizando un contenedor de tomcat integrado con su aplicación de inicio de primavera, debe poder configurar estos ajustes en el archivo de propiedades de la aplicación, utilizando las siguientes claves / valores de propiedad:

server.ssl.key-store=/opt/tomcat/conf/key-stores/ssl-keystore.jks server.ssl.key-store-password=some-complex-password server.ssl.trust-store=/opt/tomcat/conf/trust-stores/ssl-truststore.jks server.ssl.trust-store-password=some-other-complex-password server.ssl.client-auth=want

Luego, en mi aplicación web, declaro una configuración SSL específica de la siguiente manera:

@Configuration @EnableWebSecurity //In order to use @PreAuthorise() annotations later on... @EnableGlobalMethodSecurity(prePostEnabled = true) public class SSLAuthConfiguration extends WebSecurityConfigurerAdapter { @Value("${allowed.user}") private String ALLOWED_USER; @Value("${server.ssl.client.regex}") private String CN_REGEX; @Autowired private UserDetailsService userDetailsService; @Override protected void configure (final HttpSecurity http) throws Exception { http .csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/url-path-to-protect").authenticated() //Specify the URL path(s) requiring authentication... .and() .x509() //... and that x509 authentication is enabled .subjectPrincipalRegex(CN_REGEX) .userDetailsService(userDetailsService); } @Autowired //Simplified case, where the application has only one user... public void configureGlobal (final AuthenticationManagerBuilder auth) throws Exception { //... whose username is defined in the application''s properties. auth .inMemoryAuthentication() .withUser(ALLOWED_USER).password("").roles("SSL_USER"); }

}

Entonces necesito declarar el bean UserDetailsService (por ejemplo, en la clase principal de mi aplicación):

@Value("${allowed.user}") private String ALLOWED_USER; @Bean public UserDetailsService userDetailsService () { return new UserDetailsService() { @Override public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { if (username.equals(ALLOWED_USER)) { final User user = new User(username, "", AuthorityUtils.createAuthorityList("ROLE_SSL_USER")); return user; } return null; } }; }

¡Y eso es! Luego puedo agregar anotaciones @PreAuthorize ("hasRole (''ROLE_SSL_USER'')") a los métodos que deseo proteger.

Para resumir un poco, el flujo de autenticación será el siguiente:

  1. El usuario proporciona un certificado SSL;
  2. Tomcat valida contra su trust-store;
  3. El WebSecurityConfigurerAdapter personalizado recupera un "nombre de usuario" del CN ​​del certificado;
  4. La aplicación autentica al usuario asociado al nombre de usuario recuperado;
  5. A nivel del método, si se anota con @PreAuthorize ("hasRole (''SSL_USER'')"), la aplicación verificará si el usuario tiene el rol requerido.