Implementación de múltiples usuarios con Spring Security

Configuración de manejo de autenticación

Presonalización de fallo en autenticación


import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class PersonalizaFalloAutenticacion implements AuthenticationFailureHandler {
    
    @Override
    public void onAuthenticationFailure(HttpServletRequest peticion, HttpServletResponse respuesta, 
                                        AuthenticationException excepcion) throws IOException {
        respuesta.setContentType("application/json;charset=utf-8");
        
        Map<string object=""> resultado = new HashMap<>();
        resultado.put("estado", 500);
        resultado.put("mensaje", "Error en inicio de sesión: " + excepcion.getMessage());
        
        ObjectMapper mapeador = new ObjectMapper();
        String respuestaJson = mapeador.writeValueAsString(resultado);
        respuesta.getWriter().write(respuestaJson);
    }
}
</string>

Personalización de éxito en autenticación


public class PersonalizaExitoAutenticacion implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest peticion, HttpServletResponse respuesta, 
                                        Authentication autenticacion) throws IOException {
        respuesta.setContentType("application/json;charset=utf-8");
        
        Map<string object=""> resultado = new HashMap<>();
        resultado.put("estado", 200);
        resultado.put("mensaje", "Acceso concedido");
        
        ObjectMapper mapeador = new ObjectMapper();
        respuesta.getWriter().write(mapeador.writeValueAsString(resultado));
    }
}
</string>

Configuración de sgeuridad principal


@Configuration
public class ConfiguracionSeguridad extends WebSecurityConfigurerAdapter {

    @Bean
    @Primary
    UserDetailsService servicioUsuariosPrincipal() {
        return new InMemoryUserDetailsManager(
            Usuario.constructor()
                .nombreUsuario("adminusr")
                .clave("{noop}clave123")
                .roles("administrador")
                .construir()
        );
    }

    @Bean
    UserDetailsService servicioUsuariosSecundario() {
        return new InMemoryUserDetailsManager(
            Usuario.constructor()
                .nombreUsuario("usuarioreg")
                .clave("{noop}clave123")
                .roles("usuario")
                .construir()
        );
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        DaoAuthenticationProvider provider1 = new DaoAuthenticationProvider();
        provider1.setUserDetailsService(servicioUsuariosPrincipal());

        DaoAuthenticationProvider provider2 = new DaoAuthenticationProvider();
        provider2.setUserDetailsService(servicioUsuariosSecundario());

        return new ProviderManager(provider1, provider2);
    }

    @Override
    protected void configure(HttpSecurity seguridad) throws Exception {
        seguridad.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/pagina-inicio-sesion.html")
                .loginProcessingUrl("/procesar-inicio-sesion")
                .successHandler(new PersonalizaExitoAutenticacion())
                .failureHandler(new PersonalizaFalloAutenticacion())
                .usernameParameter("usuario")
                .passwordParameter("contrasena")
                .permitAll()
                .and()
                .csrf().disable();
    }
}

Controladores para gestión de usuarios


@RestController
public class ControladorUsuario {

    @GetMapping("/informacion-usuario")
    public void obtenerInfoUsuario() {
        Authentication autenticacion = SecurityContextHolder.getContext().getAuthentication();
        
        String nombre = autenticacion.getName();
        Collection extends GrantedAuthority> permisos = autenticacion.getAuthorities();
        
        System.out.println("Usuario: " + nombre);
        System.out.println("Permisos: " + permisos);
        
        new Thread(() -> {
            Authentication autenticacionHilo = SecurityContextHolder.getContext().getAuthentication();
            if (autenticacionHilo == null) {
                System.out.println("Error: contexto de seguridad no disponible");
            } else {
                System.out.println("Hilo: " + Thread.currentThread().getName());
                System.out.println("Usuario en hilo: " + autenticacionHilo.getName());
                System.out.println("Permisos en hilo: " + autenticacionHilo.getAuthorities());
            }
        }).start();
    }
}

Implemantación de servicio de usuarios


@Service
public class ServicioDetallesUsuario implements UserDetailsService {
    @Autowired
    RepositorioUsuario repositorio;

    @Override
    public UserDetails cargarUsuarioPorNombre(String nombreUsuario) {
        UsuarioEntidad usuario = repositorio.buscarPorNombre(nombreUsuario);
        if (usuario == null) {
            throw new UsernameNotFoundException("Usuario no encontrado");
        }
        return usuario;
    }
}

Configuración de base de datos


spring.datasource.usuario=root
spring.datasource.clave=secreto
spring.datasource.url=jdbc:mysql:///seguridad?codificacion=UTF-8

spring.jpa.base-datos=mysql
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

Formulario de inicio de sesión HTML


<form id="formulario-login" method="post" action="/procesar-inicio-sesion">
    <h3>Inicio de sesión</h3>
    <div>
        <label>Usuario:</label>
        <input type="text" name="usuario">
    </div>
    <div>
        <label>Contraseña:</label>
        <input type="password" name="contrasena">
    </div>
    <div>
        <input type="submit" value="Iniciar sesión">
    </div>
</form>

Etiquetas: SpringSecurity autenticación Autorización java JPA

Publicado el 9-30 06:29