Mi sono imbattuto in un problema simile e ho pensato di condividere la soluzione con cui sono arrivato.
In primo luogo, è necessario comprendere che l'autenticazione del certificato SSL verrà gestita sul lato del server Web (spiegazione di esempio con l'impostazione "clientAuth = want"). Quindi, l'app Web deve essere configurata per gestire il certificato fornito (e consentito), mapparlo a un utente, ecc.
La leggera differenza che ho con voi è che sto impacchettando la mia applicazione di avvio a molla in un archivio WAR, che viene quindi distribuito su un server di applicazioni Tomcat esistente.
file di configurazione server.xml di mio Tomcat definisce un connettore HTTPS come segue:
<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” />
piccolo commento per evitare qualsiasi confusione: keystoreFile contiene la/privato coppia di chiavi certificato utilizzato per SSL (solo), mentre truststoreFile contiene i certificati CA consentiti per l'autenticazione SSL client (si noti che è anche possibile aggiungere i certificati client direttamente a tale trust store).
Se stai usando un contenitore Tomcat incorporato con l'applicazione di avvio di primavera, si dovrebbe essere in grado di configurare queste impostazioni nelle proprietà della propria applicazione di file, utilizzando la seguente chiave di proprietà/valori:
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
Poi, sulla mia web app, dichiaro una configurazione SSL specifica come segue:
@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");
}
}
ho quindi bisogno di dichiarare l'UserDetailsService b ean (ad es. nella classe principale della mia Applicazione):
@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;
}
};
}
E il gioco è fatto! Posso quindi aggiungere le annotazioni @PreAuthorize ("hasRole ('ROLE_SSL_USER')") ai metodi che voglio proteggere.
In sintesi le cose un po ', il flusso di autenticazione sarà la seguente:
- utente fornisce certificato SSL;
- Tomcat esegue la convalida del relativo negozio di fiducia;
- Il WebSecurityConfigurerAdapter personalizzato recupera un "nome utente" dal CN del certificato;
- L'applicazione autentica l'utente associato al nome utente recuperato;
- A livello di metodo, se annotato con @PreAuthorize ("hasRole ('SSL_USER')"), l'applicazione controllerà se l'utente ha il ruolo richiesto.
Grazie per la risposta. Il collegamento fornito sembra essere il blocco completo del tomcat 7, tuttavia il server su cui verrà distribuito è una risorsa condivisa, quindi avrà un mix di elementi protetti e non protetti su di esso. Quello che cerco davvero è un modo per bloccare una singola app Web utilizzando Spring Security e i certificati client. –
Quindi è forse il contenitore di tomcat incorporato di Spring Boot che devo esaminare di più. –