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

  1. 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>

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

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

  1. 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>

  1. 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

  1. Crea una nova aplicació Spring Boot.
  2. Afegeix la dependència spring-boot-starter-security al fitxer pom.xml.
  3. 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

  1. Defineix un servei d'usuaris que gestioni usuaris en memòria.
  2. Crea dos usuaris: un amb el rol USER i un altre amb el rol ADMIN.
  3. 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

  1. Crea una pàgina de login personalitzada utilitzant Thymeleaf.
  2. 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

Mòdul 2: Conceptes bàsics de Spring Boot

Mòdul 3: Construint serveis web RESTful

Mòdul 4: Accés a dades amb Spring Boot

Mòdul 5: Seguretat a Spring Boot

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ó

Mòdul 10: Millors pràctiques i consells

© Copyright 2024. Tots els drets reservats