Configurazione automatica della sicurezza di Spring Boot

1. Introduzione

In questo articolo, daremo uno sguardo all'approccio supponente alla sicurezza di Spring Boot.

In poche parole, ci concentreremo sulla configurazione di sicurezza predefinita e su come possiamo disabilitarla o personalizzarla se necessario.

2. Configurazione di protezione predefinita

Per aggiungere sicurezza alla nostra applicazione Spring Boot, dobbiamo aggiungere la dipendenza Security Starter :

 org.springframework.boot spring-boot-starter-security 

Ciò includerà la classe SecurityAutoConfiguration , contenente la configurazione di sicurezza iniziale / predefinita.

Si noti come non abbiamo specificato la versione qui, assumendo che il progetto stia già utilizzando Boot come genitore.

In poche parole, per impostazione predefinita, l'autenticazione viene abilitata per l'applicazione. Inoltre, la negoziazione del contenuto viene utilizzata per determinare se deve essere utilizzato basic o formLogin.

Ci sono alcune proprietà predefinite, come:

spring.security.user.name spring.security.user.password

Se non configuriamo la password utilizzando la proprietà predefinita spring.security.user.password e avviamo l'applicazione, noteremo che una password predefinita viene generata casualmente e stampata nel log della console:

Using default security password: c8be15de-4488-4490-9dc6-fab3f91435c6

Per ulteriori impostazioni predefinite, vedere la sezione delle proprietà di sicurezza della pagina di riferimento delle proprietà comuni dell'applicazione Spring Boot.

3. Disattivazione della configurazione automatica

Per eliminare la configurazione automatica della sicurezza e aggiungere la nostra configurazione, è necessario escludere la classe SecurityAutoConfiguration .

Questo può essere fatto tramite una semplice esclusione:

@SpringBootApplication(exclude = { SecurityAutoConfiguration.class }) public class SpringBootSecurityApplication { public static void main(String[] args) { SpringApplication.run(SpringBootSecurityApplication.class, args); } } 

O aggiungendo una configurazione nel file application.properties :

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration

Ci sono anche alcuni casi particolari in cui questa configurazione non è abbastanza.

Ad esempio, quasi tutte le applicazioni Spring Boot vengono avviate con Actuator nel classpath. Ciò causa problemi perché un'altra classe di configurazione automatica richiede quella che abbiamo appena escluso , quindi l'applicazione non verrà avviata.

Per risolvere questo problema, dobbiamo escludere quella classe; e, in modo specifico per la situazione dell'attuatore, dobbiamo escludere ManagementWebSecurityAutoConfiguration .

3.1. Configurazione automatica della disabilitazione e del superamento della sicurezza

C'è una differenza significativa tra disabilitare l'autoconfigurazione e superarla.

Disabilitandolo, è proprio come aggiungere la dipendenza Spring Security e l'intera configurazione da zero. Questo può essere utile in diversi casi:

  1. Integrazione della sicurezza delle applicazioni con un provider di sicurezza personalizzato
  2. Migrazione a Spring Boot di un'applicazione Spring precedente con una configurazione di sicurezza già esistente

Tuttavia, la maggior parte delle volte non sarà necessario disabilitare completamente la configurazione automatica della sicurezza.

Il modo in cui è configurato Spring Boot consente di superare la sicurezza autoconfigurata aggiungendo le nostre classi di configurazione nuove / personalizzate. Questo in genere è più semplice, poiché stiamo solo personalizzando una configurazione di sicurezza esistente per soddisfare le nostre esigenze.

4. Configurazione di Spring Boot Security

Se abbiamo scelto il percorso per disabilitare la configurazione automatica della sicurezza, dobbiamo naturalmente fornire la nostra configurazione.

Come abbiamo discusso in precedenza, questa è la configurazione di sicurezza predefinita; possiamo personalizzarlo modificando il file delle proprietà.

Possiamo, ad esempio, sovrascrivere la password predefinita aggiungendo la nostra:

spring.security.user.password=password

Se vogliamo una configurazione più flessibile, ad esempio con più utenti e ruoli, dobbiamo utilizzare una classe @Configuration completa :

@Configuration @EnableWebSecurity public class BasicConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); auth .inMemoryAuthentication() .withUser("user") .password(encoder.encode("password")) .roles("USER") .and() .withUser("admin") .password(encoder.encode("admin")) .roles("USER", "ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest() .authenticated() .and() .httpBasic(); } }

L' annotazione @EnableWebSecurity è fondamentale se disabilitiamo la configurazione di sicurezza predefinita.

Se manca, l'applicazione non verrà avviata. L'annotazione è facoltativa solo se stiamo sovrascrivendo il comportamento predefinito utilizzando un WebSecurityConfigurerAdapter .

Inoltre, si noti che è necessario utilizzare PasswordEncoder per impostare le password quando si utilizza Spring Boot 2 . Per maggiori dettagli, consulta la nostra guida sul codificatore di password predefinito in Spring Security 5.

Ora, dovremmo verificare che la nostra configurazione di sicurezza si applichi correttamente con un paio di rapidi test dal vivo:

@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT) public class BasicConfigurationIntegrationTest { TestRestTemplate restTemplate; URL base; @LocalServerPort int port; @Before public void setUp() throws MalformedURLException { restTemplate = new TestRestTemplate("user", "password"); base = new URL("//localhost:" + port); } @Test public void whenLoggedUserRequestsHomePage_ThenSuccess() throws IllegalStateException, IOException { ResponseEntity response = restTemplate.getForEntity(base.toString(), String.class); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue(response.getBody().contains("Baeldung")); } @Test public void whenUserWithWrongCredentials_thenUnauthorizedPage() throws Exception { restTemplate = new TestRestTemplate("user", "wrongpassword"); ResponseEntity response = restTemplate.getForEntity(base.toString(), String.class); assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); assertTrue(response.getBody().contains("Unauthorized")); } }

L'idea è che dietro Spring Boot Security c'è, in effetti, Spring Security, quindi qualsiasi configurazione di sicurezza che può essere eseguita con questo, o qualsiasi integrazione che questo supporta può essere implementato anche in Spring Boot.

5. Configurazione automatica Spring Boot OAuth2 (utilizzando lo stack legacy)

Spring Boot dispone di un supporto di configurazione automatica dedicato per OAuth2.

Il supporto OAuth di Spring Security fornito con Spring Boot 1.x è stato rimosso nelle versioni di avvio successive al posto del supporto OAuth di prima classe fornito in bundle con Spring Security 5. Vedremo come utilizzarlo nella sezione successiva.

Per lo stack legacy (utilizzando Spring Security OAuth), prima dovremo aggiungere una dipendenza Maven per iniziare a configurare la nostra applicazione:

 org.springframework.security.oauth spring-security-oauth2 

Questa dipendenza include una serie di classi in grado di attivare il meccanismo di configurazione automatica definito nella classe OAuth2AutoConfiguration .

Ora, abbiamo più scelte per continuare, a seconda dell'ambito della nostra applicazione.

5.1. Configurazione automatica del server di autorizzazione OAuth2

Se vogliamo che la nostra applicazione sia un provider OAuth2, possiamo utilizzare @EnableAuthorizationServer .

All'avvio, noteremo nei log che le classi di configurazione automatica genereranno un ID client e un client-secret per il nostro server di autorizzazione e, naturalmente, una password casuale per l'autenticazione di base.

Using default security password: a81cb256-f243-40c0-a585-81ce1b952a98 security.oauth2.client.client-id = 39d2835b-1f87-4a77-9798-e2975f36972e security.oauth2.client.client-secret = f1463f8b-0791-46fe-9269-521b86c55b71

Queste credenziali possono essere utilizzate per ottenere un token di accesso:

curl -X POST -u 39d2835b-1f87-4a77-9798-e2975f36972e:f1463f8b-0791-46fe-9269-521b86c55b71 \ -d grant_type=client_credentials -d username=user -d password=a81cb256-f243-40c0-a585-81ce1b952a98 \ -d scope=write //localhost:8080/oauth/token

Il nostro altro articolo fornisce ulteriori dettagli sull'argomento.

5.2. Altre impostazioni di configurazione automatica di Spring Boot OAuth2

Ci sono altri casi d'uso coperti da Spring Boot OAuth2 come:

  1. Resource Server - @EnableResourceServer
  2. Applicazione client - @ EnableOAuth2Sso o @ EnableOAuth2Client

Se abbiamo bisogno che la nostra applicazione sia uno dei tipi sopra, dobbiamo solo aggiungere alcune configurazioni alle proprietà dell'applicazione, come dettagliato dai collegamenti a cui si fa riferimento sopra.

All OAuth2 specific properties can be found at Spring Boot Common Application Properties.

6. Spring Boot OAuth2 Auto-Configuration (using new stack)

To use the new stack, we need to add dependencies based on what we want to configure – an authorization server, a resource server or a client application.

Let's look at them one by one.

6.1. OAuth2 Authorization Server Support

As we saw in the previous section, the Spring Security OAuth stack offered the possibility of setting up an Authorization Server as a Spring Application. But the project has been deprecated and Spring does not support its own authorization server as of now. Instead, it's recommended to use existing well-established providers such as Okta, Keycloak, and Forgerock.

However, Spring Boot does make it easy for us to configure such providers. For an example Keycloak configuration, we can refer to either A Quick Guide to Using Keycloak with Spring Boot or Keycloak Embedded in a Spring Boot Application.

6.2. OAuth2 Resource Server Support

To include support for a resource server, we need to add this dependency:

 org.springframework.boot spring-boot-starter-oauth2-resource-server 

For the latest version information, head over to Maven Central.

Additionally, in our security configuration, we need to include the oauth2ResourceServer() DSL:

@Configuration public class JWTSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http ... .oauth2ResourceServer(oauth2 -> oauth2.jwt()); ... } }

Our OAuth 2.0 Resource Server With Spring Security 5 gives an in-depth view of this topic.

6.3. OAuth2 Client Support

Similar to how we configured a resource server, a client application also needs its own dependencies and DSLs.

Here's the specific dependency for OAuth2 client support:

 org.springframework.boot spring-boot-starter-oauth2-client  

The latest version can be found at Maven Central.

Spring Security 5 also provides first-class login support via its oath2Login() DSL.

For details on SSO support in the new stack, please refer to our Simple Single Sign-On with Spring Security OAuth2.

7. Spring Boot 2 Security vs Spring Boot 1 Security

Compared to Spring Boot 1, Spring Boot 2 has greatly simplified the auto-configuration.

In Spring Boot 2, if we want our own security configuration, we can simply add a custom WebSecurityConfigurerAdapter. This will disable the default auto-configuration and enable our custom security configuration.

Spring Boot 2 uses most of Spring Security’s defaults. Because of this, some of the endpoints that were unsecured by default in Spring Boot 1 are now secured by default.

These endpoints include static resources such as /css/**, /js/**, /images/**, /webjars/**, /**/favicon.ico, and the error endpoint. If we need to allow unauthenticated access to these endpoints, we can explicitly configure that.

To simplify the security-related configuration, Spring Boot 2 has removed the following Spring Boot 1 properties:

security.basic.authorize-mode security.basic.enabled security.basic.path security.basic.realm security.enable-csrf security.headers.cache security.headers.content-security-policy security.headers.content-security-policy-mode security.headers.content-type security.headers.frame security.headers.hsts security.headers.xss security.ignored security.require-ssl security.sessions

8. Conclusion

In this article, we focused on the default security configuration provided by Spring Boot. We saw how the security auto-configuration mechanism can be disabled or overridden and how a new security configuration can be applied.

Il codice sorgente per OAuth2 può essere trovato sul nostro repository GitHub OAuth2, per lo stack legacy e nuovo. Il resto del codice può essere trovato sui tutorial GitHub.