Automatische Konfiguration der Spring Boot-Sicherheit

1. Einleitung

In diesem Artikel werfen wir einen Blick auf den von Spring Boot vertretenen Sicherheitsansatz.

Einfach ausgedrückt, konzentrieren wir uns auf die Standardsicherheitskonfiguration und darauf, wie wir sie bei Bedarf deaktivieren oder anpassen können.

2. Standard-Sicherheits-Setup

Um unserer Spring Boot-Anwendung Sicherheit hinzuzufügen, müssen wir die Sicherheitsstarter-Abhängigkeit hinzufügen :

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

Dies umfasst die SecurityAutoConfiguration- Klasse, die die anfängliche / standardmäßige Sicherheitskonfiguration enthält.

Beachten Sie, dass wir die Version hier nicht angegeben haben, mit der Annahme, dass das Projekt Boot bereits als übergeordnetes Element verwendet.

Einfach ausgedrückt, wird die Authentifizierung standardmäßig für die Anwendung aktiviert. Außerdem wird die Inhaltsverhandlung verwendet, um zu bestimmen, ob basic oder formLogin verwendet werden soll.

Es gibt einige vordefinierte Eigenschaften, wie z.

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

Wenn wir das Kennwort nicht mit der vordefinierten Eigenschaft spring.security.user.password konfigurieren und die Anwendung starten, werden wir feststellen, dass ein Standardkennwort zufällig generiert und im Konsolenprotokoll gedruckt wird:

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

Weitere Standardeinstellungen finden Sie im Abschnitt Sicherheitseigenschaften auf der Referenzseite Eigenschaften von Spring Boot Common Application Properties.

3. Deaktivieren Sie die automatische Konfiguration

Um die automatische Sicherheitskonfiguration zu verwerfen und unsere eigene Konfiguration hinzuzufügen, müssen Sie die SecurityAutoConfiguration- Klasse ausschließen.

Dies kann durch einen einfachen Ausschluss erfolgen:

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

Oder indem Sie der Datei application.properties eine Konfiguration hinzufügen :

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

Es gibt auch einige besondere Fälle, in denen dieses Setup nicht ganz ausreicht.

Beispielsweise wird fast jede Spring Boot-Anwendung mit Actuator im Klassenpfad gestartet. Dies führt zu Problemen, da eine andere Klasse für die automatische Konfiguration die gerade ausgeschlossene benötigt , sodass die Anwendung nicht gestartet werden kann.

Um dieses Problem zu beheben, müssen wir diese Klasse ausschließen. Speziell für die Actuator-Situation müssen wir ManagementWebSecurityAutoConfiguration ausschließen .

3.1. Deaktivieren oder Überschreiten der automatischen Sicherheitskonfiguration

Es gibt einen signifikanten Unterschied zwischen dem Deaktivieren der Autokonfiguration und dem Überschreiten.

Durch Deaktivieren wird die Spring Security-Abhängigkeit und das gesamte Setup von Grund auf neu hinzugefügt. Dies kann in mehreren Fällen nützlich sein:

  1. Integration der Anwendungssicherheit in einen benutzerdefinierten Sicherheitsanbieter
  2. Migrieren einer älteren Spring-Anwendung mit bereits vorhandenem Sicherheits-Setup - zu Spring Boot

Meistens müssen wir die automatische Sicherheitskonfiguration jedoch nicht vollständig deaktivieren.

Die Art und Weise, wie Spring Boot konfiguriert ist, ermöglicht es, die automatisch konfigurierte Sicherheit zu übertreffen, indem Sie unsere neuen / benutzerdefinierten Konfigurationsklassen hinzufügen. Dies ist in der Regel einfacher, da wir lediglich ein vorhandenes Sicherheits-Setup anpassen, um unsere Anforderungen zu erfüllen.

4. Konfigurieren der Spring Boot-Sicherheit

Wenn wir den Weg zum Deaktivieren der automatischen Sicherheitskonfiguration gewählt haben, müssen wir natürlich unsere eigene Konfiguration bereitstellen.

Wie bereits erwähnt, ist dies die Standardsicherheitskonfiguration. Wir können es anpassen, indem wir die Eigenschaftendatei ändern.

Wir können beispielsweise das Standardkennwort überschreiben, indem wir unser eigenes hinzufügen:

spring.security.user.password=password

Wenn wir eine flexiblere Konfiguration mit beispielsweise mehreren Benutzern und Rollen wünschen, müssen wir eine vollständige @ Configuration- Klasse verwenden:

@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(); } }

Die Annotation @EnableWebSecurity ist entscheidend, wenn wir die Standardsicherheitskonfiguration deaktivieren.

Wenn dies fehlt, kann die Anwendung nicht gestartet werden. Die Anmerkung ist nur optional, wenn wir nur das Standardverhalten mithilfe eines WebSecurityConfigurerAdapter überschreiben .

Beachten Sie außerdem, dass wir den PasswordEncoder verwenden müssen , um die Kennwörter festzulegen, wenn Sie Spring Boot 2 verwenden . Weitere Informationen finden Sie in unserem Handbuch zum Standardkennwortcodierer in Spring Security 5.

Jetzt sollten wir anhand einiger schneller Live-Tests überprüfen, ob unsere Sicherheitskonfiguration korrekt ist:

@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")); } }

Die Idee ist, dass hinter Spring Boot Security tatsächlich Spring Security steht, sodass jede Sicherheitskonfiguration, die mit dieser Konfiguration durchgeführt werden kann, oder jede Integration, die diese unterstützt, auch in Spring Boot implementiert werden kann.

5. Spring Boot OAuth2 Auto-Konfiguration (unter Verwendung eines Legacy-Stacks)

Spring Boot bietet eine dedizierte Unterstützung für die automatische Konfiguration von OAuth2.

Spring Security OAuth support that came with Spring Boot 1.x was removed in later boot versions in lieu of first class OAuth support that comes bundled with Spring Security 5. We'll see how to use that in the next section.

For the legacy stack (using Spring Security OAuth), first we'll need to add a Maven dependency to start setting up our application:

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

This dependency includes a set of classes that are capable of triggering the auto-configuration mechanism defined in OAuth2AutoConfiguration class.

Now, we have multiple choices to continue, depending on the scope of our application.

5.1. OAuth2 Authorization Server Auto-Configuration

If we want our application to be an OAuth2 provider, we can use @EnableAuthorizationServer.

On startup, we'll notice in the logs that the auto-configuration classes will generate a client id and a client-secret for our authorization server and of course a random password for basic authentication.

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

These credentials can be used to obtain an access token:

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

Our another article provides further details on the subject.

5.2. Other Spring Boot OAuth2 Auto-Configuration Settings

There are some other use cases covered by Spring Boot OAuth2 like:

  1. Resource Server – @EnableResourceServer
  2. Client Application – @EnableOAuth2Sso or @EnableOAuth2Client

If we need our application to be one of the types above we just have to add some configuration to application properties, as detailed by the links referenced above.

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.

Der Quellcode für OAuth2 befindet sich in unserem OAuth2 GitHub-Repository für Legacy und neuen Stack. Der Rest des Codes ist in den Tutorials GitHub zu finden.