En aquest tema, aprendrem com configurar Spring Security per protegir les nostres aplicacions Spring Boot. Spring Security és un marc potent i altament personalitzable per a l'autenticació i l'autorització en aplicacions Java.
Objectius
- Entendre els conceptes bàsics de Spring Security.
- Configurar Spring Security en una aplicació Spring Boot.
- Personalitzar la configuració de seguretat per a diferents necessitats.
Conceptes Clau
- Dependències de Spring Security
Per començar a utilitzar Spring Security, necessitem afegir les dependències necessàries al nostre projecte. Si estem utilitzant Maven, afegirem les següents dependències al fitxer pom.xml
:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
- Configuració Bàsica de Seguretat
Spring Boot proporciona una configuració de seguretat per defecte que protegeix totes les rutes de la nostra aplicació. Per personalitzar aquesta configuració, crearem una classe de configuració que estengui WebSecurityConfigurerAdapter
.
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/public/**").permitAll() // Permet l'accés a rutes públiques .anyRequest().authenticated() // Requereix autenticació per a qualsevol altra ruta .and() .formLogin() .loginPage("/login") // Especifica la pàgina de login personalitzada .permitAll() .and() .logout() .permitAll(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
- Autenticació d'Usuaris
Per gestionar els usuaris i les seves credencials, podem utilitzar un servei d'usuaris personalitzat. Aquí hi ha un exemple de com definir un servei d'usuaris:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.provisioning.InMemoryUserDetailsManager; @Configuration public class UserConfig { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder()); } @Bean public UserDetailsService userDetailsService() { InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); manager.createUser(User.withUsername("user").password(passwordEncoder().encode("password")).roles("USER").build()); manager.createUser(User.withUsername("admin").password(passwordEncoder().encode("admin")).roles("ADMIN").build()); return manager; } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
- Personalització de la Pàgina de Login
Podem personalitzar la pàgina de login per adaptar-la a les necessitats de la nostra aplicació. Aquí hi ha un exemple de com crear una pàgina de login personalitzada:
<!-- src/main/resources/templates/login.html --> <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Login</title> </head> <body> <h1>Login</h1> <form th:action="@{/login}" method="post"> <div> <label>Username:</label> <input type="text" name="username"/> </div> <div> <label>Password:</label> <input type="password" name="password"/> </div> <div> <button type="submit">Login</button> </div> </form> </body> </html>
- Configuració de Rutes Segures
Podem configurar rutes segures per a diferents rols d'usuari. Aquí hi ha un exemple de com permetre l'accés a rutes específiques només per a usuaris amb el rol ADMIN
:
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") // Només els usuaris amb el rol ADMIN poden accedir a /admin/** .antMatchers("/public/**").permitAll() // Permet l'accés a rutes públiques .anyRequest().authenticated() // Requereix autenticació per a qualsevol altra ruta .and() .formLogin() .loginPage("/login") // Especifica la pàgina de login personalitzada .permitAll() .and() .logout() .permitAll(); }
Exercicis Pràctics
Exercici 1: Configuració Bàsica de Seguretat
- Crea una nova aplicació Spring Boot.
- Afegeix la dependència
spring-boot-starter-security
al fitxerpom.xml
. - Crea una classe de configuració de seguretat que permeti l'accés a rutes públiques i requereixi autenticació per a qualsevol altra ruta.
Exercici 2: Autenticació d'Usuaris
- Defineix un servei d'usuaris que gestioni usuaris en memòria.
- Crea dos usuaris: un amb el rol
USER
i un altre amb el rolADMIN
. - Configura la seguretat per permetre l'accés a rutes específiques només per a usuaris amb el rol
ADMIN
.
Exercici 3: Personalització de la Pàgina de Login
- Crea una pàgina de login personalitzada utilitzant Thymeleaf.
- Configura Spring Security per utilitzar la pàgina de login personalitzada.
Solucions
Solució a l'Exercici 1
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/public/**").permitAll() .anyRequest().authenticated() .and() .formLogin() .permitAll() .and() .logout() .permitAll(); } }
Solució a l'Exercici 2
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class UserConfig { @Bean public UserDetailsService userDetailsService() { InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); manager.createUser(User.withUsername("user").password(passwordEncoder().encode("password")).roles("USER").build()); manager.createUser(User.withUsername("admin").password(passwordEncoder().encode("admin")).roles("ADMIN").build()); return manager; } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder()); } }
Solució a l'Exercici 3
<!-- src/main/resources/templates/login.html --> <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Login</title> </head> <body> <h1>Login</h1> <form th:action="@{/login}" method="post"> <div> <label>Username:</label> <input type="text" name="username"/> </div> <div> <label>Password:</label> <input type="password" name="password"/> </div> <div> <button type="submit">Login</button> </div> </form> </body> </html>
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/public/**").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll(); } }
Conclusió
En aquest tema, hem après com configurar Spring Security per protegir les nostres aplicacions Spring Boot. Hem vist com afegir les dependències necessàries, configurar la seguretat bàsica, gestionar usuaris i personalitzar la pàgina de login. Amb aquests coneixements, estem preparats per implementar una seguretat robusta a les nostres aplicacions.
Curs de Spring Boot
Mòdul 1: Introducció a Spring Boot
- Què és Spring Boot?
- Configuració del teu entorn de desenvolupament
- Creant la teva primera aplicació Spring Boot
- Entenent l'estructura del projecte Spring Boot
Mòdul 2: Conceptes bàsics de Spring Boot
- Anotacions de Spring Boot
- Injecció de dependències a Spring Boot
- Configuració de Spring Boot
- Propietats de Spring Boot
Mòdul 3: Construint serveis web RESTful
- Introducció als serveis web RESTful
- Creant controladors REST
- Gestionant mètodes HTTP
- Gestió d'excepcions en REST
Mòdul 4: Accés a dades amb Spring Boot
- Introducció a Spring Data JPA
- Configuració de fonts de dades
- Creant entitats JPA
- Utilitzant repositoris de Spring Data
- Mètodes de consulta a Spring Data JPA
Mòdul 5: Seguretat a Spring Boot
- Introducció a Spring Security
- Configuració de Spring Security
- Autenticació i autorització d'usuaris
- Implementant autenticació JWT
Mòdul 6: Proves a Spring Boot
Mòdul 7: Funcions avançades de Spring Boot
Mòdul 8: Desplegant aplicacions Spring Boot
Mòdul 9: Rendiment i monitorització
- Optimització del rendiment
- Monitorització amb Spring Boot Actuator
- Utilitzant Prometheus i Grafana
- Gestió de registres i logs