1. Introducción
En este artículo, veremos el enfoque obstinado de la seguridad de Spring Boot.
En pocas palabras, nos centraremos en la configuración de seguridad predeterminada y cómo podemos desactivarla o personalizarla si es necesario.
2. Configuración de seguridad predeterminada
Para agregar seguridad a nuestra aplicación Spring Boot, necesitamos agregar la dependencia de inicio de seguridad :
org.springframework.boot spring-boot-starter-security
Esto incluirá la clase SecurityAutoConfiguration , que contiene la configuración de seguridad inicial / predeterminada.
Observe cómo no especificamos la versión aquí, asumiendo que el proyecto ya está usando Boot como padre.
En pocas palabras, de forma predeterminada, la autenticación se habilita para la aplicación. Además, la negociación de contenido se usa para determinar si se debe usar basic o formLogin.
Hay algunas propiedades predefinidas, como:
spring.security.user.name spring.security.user.password
Si no configuramos la contraseña usando la propiedad predefinida spring.security.user.password e iniciamos la aplicación, notaremos que una contraseña predeterminada se genera aleatoriamente y se imprime en el registro de la consola:
Using default security password: c8be15de-4488-4490-9dc6-fab3f91435c6
Para obtener más valores predeterminados, consulte la sección de propiedades de seguridad de la página de referencia Propiedades de aplicaciones comunes de Spring Boot.
3. Desactivación de la configuración automática
Para descartar la configuración automática de seguridad y agregar nuestra propia configuración, debemos excluir la clase SecurityAutoConfiguration .
Esto se puede hacer mediante una simple exclusión:
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class }) public class SpringBootSecurityApplication { public static void main(String[] args) { SpringApplication.run(SpringBootSecurityApplication.class, args); } }
O agregando alguna configuración en el archivo application.properties :
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration
También hay algunos casos particulares en los que esta configuración no es suficiente.
Por ejemplo, casi todas las aplicaciones de Spring Boot se inician con Actuator en la ruta de clases. Esto causa problemas porque otra clase de configuración automática necesita la que acabamos de excluir , por lo que la aplicación no se iniciará.
Para solucionar este problema, debemos excluir esa clase; y, específicamente para la situación del actuador, necesitamos excluir ManagementWebSecurityAutoConfiguration .
3.1. Desactivación frente a superación de la configuración automática de seguridad
Existe una diferencia significativa entre deshabilitar la configuración automática y superarla.
Al deshabilitarlo, es como agregar la dependencia de Spring Security y toda la configuración desde cero. Esto puede resultar útil en varios casos:
- Integrando la seguridad de la aplicación con un proveedor de seguridad personalizado
- Migración de una aplicación Spring heredada con configuración de seguridad ya existente - a Spring Boot
Pero, la mayoría de las veces, no necesitaremos deshabilitar completamente la configuración automática de seguridad.
La forma en que Spring Boot está configurado permite superar la seguridad autoconfigurada al agregar nuestras clases de configuración nuevas / personalizadas. Por lo general, esto es más fácil, ya que solo estamos personalizando una configuración de seguridad existente para satisfacer nuestras necesidades.
4. Configuración de Spring Boot Security
Si hemos elegido la ruta de deshabilitar la configuración automática de seguridad, naturalmente necesitamos proporcionar nuestra propia configuración.
Como hemos comentado antes, esta es la configuración de seguridad predeterminada; podemos personalizarlo modificando el archivo de propiedades.
Podemos, por ejemplo, anular la contraseña predeterminada agregando la nuestra:
spring.security.user.password=password
Si queremos una configuración más flexible, con múltiples usuarios y roles, por ejemplo, necesitamos hacer uso de una clase @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(); } }
La anotación @EnableWebSecurity es crucial si deshabilitamos la configuración de seguridad predeterminada.
Si falta, la aplicación no se iniciará. La anotación solo es opcional si simplemente anulamos el comportamiento predeterminado usando un WebSecurityConfigurerAdapter .
Además, tenga en cuenta que necesitamos usar PasswordEncoder para establecer las contraseñas cuando usamos Spring Boot 2 . Para obtener más detalles, consulte nuestra guía sobre el codificador de contraseña predeterminado en Spring Security 5.
Ahora, debemos verificar que nuestra configuración de seguridad se aplique correctamente con un par de pruebas rápidas en 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")); } }
La idea es que detrás de Spring Boot Security está, de hecho, Spring Security, por lo que cualquier configuración de seguridad que se pueda hacer con este, o cualquier integración que este soporte, también se puede implementar en Spring Boot.
5. Configuración automática de Spring Boot OAuth2 (usando pila heredada)
Spring Boot tiene un soporte de configuración automática dedicado para OAuth2.
El soporte de Spring Security OAuth que venía con Spring Boot 1.x se eliminó en versiones de arranque posteriores en lugar del soporte de OAuth de primera clase que viene incluido con Spring Security 5. Veremos cómo usarlo en la siguiente sección.
Para la pila heredada (usando Spring Security OAuth), primero necesitaremos agregar una dependencia de Maven para comenzar a configurar nuestra aplicación:
org.springframework.security.oauth spring-security-oauth2
Esta dependencia incluye un conjunto de clases que son capaces de activar el mecanismo de configuración automática definido en la clase OAuth2AutoConfiguration .
Ahora, tenemos múltiples opciones para continuar, dependiendo del alcance de nuestra aplicación.
5.1. Configuración automática del servidor de autorización OAuth2
Si queremos que nuestra aplicación sea un proveedor OAuth2, podemos usar @EnableAuthorizationServer .
Al inicio, notaremos en los registros que las clases de configuración automática generarán una identificación de cliente y un secreto de cliente para nuestro servidor de autorización y, por supuesto, una contraseña aleatoria para la autenticación básica.
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
Estas credenciales se pueden utilizar para obtener un token de acceso:
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
Nuestro otro artículo proporciona más detalles sobre el tema.
5.2. Otras opciones de configuración automática de Spring Boot OAuth2
Hay algunos otros casos de uso cubiertos por Spring Boot OAuth2 como:
- Servidor de recursos - @EnableResourceServer
- Aplicación de cliente: @ EnableOAuth2Sso o @ EnableOAuth2Client
Si necesitamos que nuestra aplicación sea uno de los tipos anteriores, solo tenemos que agregar alguna configuración a las propiedades de la aplicación, como se detalla en los enlaces mencionados anteriormente.
Todas las propiedades específicas de OAuth2 se pueden encontrar en Spring Boot Common Application Properties.
6. Configuración automática de Spring Boot OAuth2 (usando una nueva pila)
Para usar la nueva pila, necesitamos agregar dependencias según lo que queramos configurar: un servidor de autorización, un servidor de recursos o una aplicación cliente.
Veámoslos uno por uno.
6.1. Compatibilidad con el servidor de autorización OAuth2
Como vimos en la sección anterior, la pila Spring Security OAuth ofrecía la posibilidad de configurar un servidor de autorización como una aplicación Spring. Pero el proyecto ha quedado obsoleto y Spring no admite su propio servidor de autorización a partir de ahora. En su lugar, se recomienda utilizar proveedores existentes bien establecidos como Okta, Keycloak y 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.
El código fuente de OAuth2 se puede encontrar en nuestro repositorio de GitHub de OAuth2, para pila nueva y heredada. El resto del código se puede encontrar en los tutoriales de GitHub.