Adición de mecanismos de seguridad

parent 21c72f28
......@@ -84,6 +84,18 @@
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>
......
......@@ -3,28 +3,20 @@ package com.carpooling.carpoolingaoraha;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication(scanBasePackages = {
"com.carpooling.carpoolingaoraha.services",
"com.carpooling.carpoolingaoraha.repositorios",
"com.carpooling.carpoolingaoraha.rest"
"com.carpooling.carpoolingaoraha.rest",
"com.carpooling.carpoolingaoraha.seguridad"
})
@EntityScan(basePackages = "com.carpooling.carpoolingaoraha.entidades")
@EnableCaching
public class CarPoolingAorAhaApplication {
public static void main(String[] args) {
SpringApplication.run(CarPoolingAorAhaApplication.class, args);
/*SistemaCarPooling sis = new SistemaCarPooling();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date yourDate = null;
try {
yourDate = sdf.parse("1992-07-26");
} catch (ParseException e) {
throw new RuntimeException(e);
}
Usuario usuario = new Usuario("Alvaro", "Alonso", yourDate, "78162640S", 670988953, "aor00039@red.ujaen.es", "hola", Usuario.Rol.PASAJERO, sis);
ServicioCarPooling servicioCarPooling = new ServicioCarPooling();
servicioCarPooling.insertarUsuario(usuario);*/
}
......
......@@ -47,7 +47,7 @@ public class ReservaRepository {
em.merge(reserva);
}
@CacheEvict(value = "reservas", key = "#reserva.idReserva")
@CacheEvict(value = "reservas", key = "id")
public void eliminarReserva(int id) {
Reserva reserva = em.find(Reserva.class, id);
if (reserva != null) {
......
......@@ -10,7 +10,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.TypedQuery;
import java.util.List;
import java.util.Optional;
......
......@@ -45,7 +45,7 @@ public class ControladorREST {
@PostMapping("/usuarios")
ResponseEntity<DTOUsuario> altaUsuario(@RequestBody DTOUsuario usuario){
try {
Usuario u = servicioCarPooling.altaCliente(usuario.altaUsuario());
Usuario u = servicioCarPooling.registrarUsuario(usuario.altaUsuario());
return ResponseEntity.status(HttpStatus.CREATED).body(new DTOUsuario(u));
} catch (UsuarioYaRegistrado e) {
return ResponseEntity.status(HttpStatus.CONFLICT).build();
......
package com.carpooling.carpoolingaoraha.seguridad;
import com.carpooling.carpoolingaoraha.entidades.Usuario;
import com.carpooling.carpoolingaoraha.services.ServicioCarPooling;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class ServicioDatosCliente implements UserDetailsService {
@Autowired
ServicioCarPooling servicioCarPooling;
@Override
public UserDetails loadUserByUsername(String dni) throws UsernameNotFoundException {
Usuario cliente = servicioCarPooling.verUsuario(dni)
.orElseThrow(() -> new UsernameNotFoundException(""));
return User.withUsername(cliente.getDNI())
.roles("USUARIO").password(cliente.getClaveAcceso())
.build();
}
}
package com.carpooling.carpoolingaoraha.seguridad;
import com.carpooling.carpoolingaoraha.utils.CachedBCryptPasswordEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager;
public class ServicioSeguridadCarpooling {
@Bean
PasswordEncoder passwordEncoder() {
//return new BCryptPasswordEncoder();
return new CachedBCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.httpBasic(httpBasic -> httpBasic.realmName("carpooling"))
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session.disable())
.authorizeHttpRequests(request -> request.requestMatchers(HttpMethod.POST, "http://localhost:8080/")
.permitAll())
.authorizeHttpRequests(request -> request.requestMatchers("http://localhost:8080/**")
.access(new WebExpressionAuthorizationManager("hasRole('USUARIO') and #dni == principal.username")));
return httpSecurity.build();
}
}
......@@ -12,6 +12,7 @@ import com.carpooling.carpoolingaoraha.repositorios.ViajeRepository;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
......@@ -44,7 +45,7 @@ public class ServicioCarPooling {
//AltaViaje???
//Cacheable
@Transactional
public Usuario altaCliente(@NotNull @Valid Usuario usuario) {
public Usuario registrarUsuario(@NotNull @Valid Usuario usuario) {
Optional<Usuario> test = repositorioUsuario.buscar(usuario.getDNI());
if (test.isPresent()) {
throw new UsuarioYaRegistrado();
......
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package com.carpooling.carpoolingaoraha.utils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author ajrueda
*/
public class CachedBCryptPasswordEncoder extends BCryptPasswordEncoder {
static Map<String, CharSequence> cache = new HashMap<>();
public CachedBCryptPasswordEncoder() {
super();
}
public CachedBCryptPasswordEncoder(int strength) {
super(strength);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
CharSequence cachedMatch = cache.get(encodedPassword);
if (cachedMatch != null && cachedMatch.equals(rawPassword)) {
return true;
}
boolean result = super.matches(rawPassword, encodedPassword);
if (result == true) {
cache.put(encodedPassword, rawPassword);
}
return result;
}
}
package com.carpooling.carpoolingaoraha.utils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* Codificador sencillo para contraseñas basado en Md5 (no seguro)
* @author ajrueda
*/
public class CodificadorPassword {
static BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
private CodificadorPassword() {
}
public static String codificar(String cadena) {
return encoder.encode(cadena);
}
public static boolean igual(String password, String passwordCodificado) {
return encoder.matches(password, passwordCodificado);
}
}
......@@ -6,4 +6,6 @@ spring.profiles.active=test
spring.jpa.properties.javax.persistence.schema-generation.database.action: drop-and-create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
\ No newline at end of file
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.cache.type=NONE
spring.security.enabled=false
\ No newline at end of file
......@@ -2,7 +2,7 @@
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<cache name="clientes"
<cache name="usuarios"
maxElementsInMemory="100"
eternal="false"
overflowToDisk="false" />
......
......@@ -19,9 +19,8 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import java.text.SimpleDateFormat;
import java.util.*;
......@@ -33,8 +32,7 @@ public class ControladorRESTTEST {
int localPort;
@Autowired
MappingJackson2HttpMessageConverter springBoot;
MappingJackson2HttpMessageConverter springBootJacksonConverter;
TestRestTemplate restTemplate;
@PostConstruct
......@@ -46,6 +44,7 @@ public class ControladorRESTTEST {
restTemplate = new TestRestTemplate(restTemplateBuilder);
}
@Test
@DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD)
public void altaUsuario(){
Date fecha = new Date(2000, 12, 1);
DTOUsuario usuario = new DTOUsuario("Fernando", "Alonso Diaz",fecha, "78062640S", 670988953, "hola@gmail.com", "1234", Usuario.Rol.CONDUCTOR);
......@@ -55,6 +54,16 @@ public class ControladorRESTTEST {
);
Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.CREATED);
ResponseEntity<DTOUsuario> respuestaLogin = restTemplate
.withBasicAuth(usuario.DNI(), usuario.claveAcceso())
.getForEntity(
"/usuarios/{dni}",
DTOUsuario.class,
usuario.DNI()
);
Assertions.assertThat(respuestaLogin.getStatusCode()).isEqualTo(HttpStatus.OK);
}
@Test
......
......@@ -2,15 +2,10 @@ package com.carpooling.carpoolingaoraha.services;
import com.carpooling.carpoolingaoraha.entidades.*;
import com.carpooling.carpoolingaoraha.entidades.Usuario.*;
import com.carpooling.carpoolingaoraha.repositorios.ReservaRepository;
import com.carpooling.carpoolingaoraha.repositorios.UsuarioRepository;
import org.assertj.core.api.Assertions;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.validation.ConstraintViolationException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
......@@ -51,7 +46,7 @@ public class ServicioCarPoolingTest
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date yourDate = sdf.parse("1992-07-26");
Usuario usuario = new Usuario("Perico", "Alonso", yourDate, "78162640S", 670988953, "aor00039@red.ujaen.es", "hola", Rol.PASAJERO);
Usuario usuarioGuardado = servicio.altaCliente(usuario);
Usuario usuarioGuardado = servicio.registrarUsuario(usuario);
assertNotNull(usuarioGuardado);
// Validar propiedades específicas del usuario guardado
......@@ -89,7 +84,7 @@ public class ServicioCarPoolingTest
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date yourDate = sdf.parse("1992-07-26");
Usuario usuario = new Usuario("Perico", "Alonso", yourDate, sb.toString(), 670988953, "aor00039@red.ujaen.es", "hola", Rol.PASAJERO);
servicio.altaCliente(usuario);
servicio.registrarUsuario(usuario);
// Modificar los datos del usuario
usuario.setNombre("NuevoNombre");
......@@ -198,7 +193,7 @@ public class ServicioCarPoolingTest
Usuario usuario = new Usuario();
usuario.setDNI(dni);
servicio.altaCliente(usuario);
servicio.registrarUsuario(usuario);
Reserva reserva = servicio.crearReserva(dni, new Reserva());
......@@ -212,7 +207,7 @@ public class ServicioCarPoolingTest
Usuario usuario = new Usuario();
usuario.setDNI(dni);
servicio.altaCliente(usuario);
servicio.registrarUsuario(usuario);
usuario.setRol(Rol.AMBOS);
Reserva reserva = servicio.crearReserva(dni, new Reserva());
Solicitud snueva = new Solicitud(reserva.getIdReserva(), usuario.getDNI());
......@@ -241,7 +236,7 @@ public class ServicioCarPoolingTest
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date yourDate = sdf.parse("1992-07-26");
Usuario usuario = new Usuario("Perico", "Alonso", yourDate, sb.toString(), 670988953, "aor00039@red.ujaen.es", "hola", Rol.PASAJERO);
Usuario usuarioGuardado = servicio.altaCliente(usuario);
Usuario usuarioGuardado = servicio.registrarUsuario(usuario);
String dni = sb.toString();
double nuevaPuntuacion = 5;
// Ejecutar el método que se va a probar
......@@ -270,7 +265,7 @@ public class ServicioCarPoolingTest
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date yourDate = sdf.parse("1992-07-26");
Usuario usuario = new Usuario("Perico", "Alonso", yourDate, sb.toString(), 670988953, "aor00039@red.ujaen.es", "hola", Usuario.Rol.PASAJERO);
servicio.altaCliente(usuario);
servicio.registrarUsuario(usuario);
int idReserva = 1;
Reserva reserva = servicio.crearReserva(usuario.getDNI(), new Reserva());
......@@ -301,7 +296,7 @@ public class ServicioCarPoolingTest
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date yourDate = sdf.parse("1992-07-26");
Usuario usuario = new Usuario("Perico", "Alonso", yourDate, sb.toString(), 670988953, "aor00039@red.ujaen.es", "hola", Rol.PASAJERO);
servicio.altaCliente(usuario);
servicio.registrarUsuario(usuario);
// Ejecutar el método que se va a probar
assertDoesNotThrow(() -> servicio.darseDeBaja(usuario.getDNI()));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment