Commit f67d63c9 by Antonio Rueda

Actualización de la configuración de Spring Security al método nuevo.

parent c7e765a3
......@@ -39,40 +39,50 @@ import org.springframework.web.bind.annotation.RestController;
/**
* Controlador REST para los servicios de UjaCoin
*
* @author ajrueda
*/
@RestController
@RequestMapping("/ujacoin")
public class ControladorREST {
@Autowired
ServicioUjaCoin servicios;
/** Handler para excepciones de violación de restricciones */
/**
* Handler para excepciones de violación de restricciones
*/
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public void handlerViolacionRestricciones(ConstraintViolationException e) {
// return ResponseEntity.badRequest().body(e.getMessage());
}
/** Handler para excepciones de accesos de usuarios no registrados */
/**
* Handler para excepciones de accesos de usuarios no registrados
*/
@ExceptionHandler(ClienteNoRegistrado.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public void handlerClienteNoRegistrado(ClienteNoRegistrado e) {
}
/** Creación de clientes */
/**
* Creación de clientes
*/
@PostMapping("/clientes")
ResponseEntity<DTOCuenta> altaCliente(@RequestBody DTOCliente cliente) {
try {
Cuenta cuenta = servicios.altaCliente(cliente.aCliente());
return ResponseEntity.status(HttpStatus.CREATED).body(new DTOCuenta(cuenta));
}
catch(ClienteYaRegistrado e) {
} catch (ClienteYaRegistrado e) {
return ResponseEntity.status(HttpStatus.CONFLICT).build();
}
}
/** Login de clientes (temporal hasta incluir autenticación mediante Spring Security */
/**
* Login de clientes (temporal hasta incluir autenticación mediante Spring
* Security
*/
@GetMapping("/clientes/{dni}")
ResponseEntity<DTOCliente> verCliente(@PathVariable String dni) {
Optional<Cliente> cliente = servicios.verCliente(dni);
......@@ -81,19 +91,22 @@ public class ControladorREST {
.orElse(ResponseEntity.notFound().build());
}
/** Registrar tarjetas */
/**
* Registrar tarjetas
*/
@PostMapping("/clientes/{dni}/tarjetas")
ResponseEntity<Void> altaTarjeta(@PathVariable String dni, @RequestBody DTOTarjeta tarjeta) {
try {
servicios.registrarTarjeta(dni, tarjeta.aTarjeta());
return ResponseEntity.status(HttpStatus.CREATED).build();
}
catch(TarjetaYaRegistrada e) {
} catch (TarjetaYaRegistrada e) {
return ResponseEntity.status(HttpStatus.CONFLICT).build();
}
}
/** Listar tarjetas */
/**
* Listar tarjetas
*/
@GetMapping("/clientes/{dni}/tarjetas")
@ResponseStatus(HttpStatus.OK)
List<DTOTarjeta> verTarjetas(@PathVariable String dni) {
......@@ -101,7 +114,9 @@ public class ControladorREST {
.map(t -> new DTOTarjeta(t)).toList();
}
/** Obtener una tarjeta concreta */
/**
* Obtener una tarjeta concreta
*/
@GetMapping("/clientes/{dni}/tarjetas/{num}")
ResponseEntity<DTOTarjeta> verTarjeta(@PathVariable String dni, @PathVariable String num) {
return servicios.verTarjetas(dni).stream()
......@@ -110,15 +125,19 @@ public class ControladorREST {
.map(t -> ResponseEntity.ok(new DTOTarjeta(t)))
.orElse(ResponseEntity.notFound().build());
}
/** Crear cuentas adicionales */
/**
* Crear cuentas adicionales
*/
@PostMapping("/clientes/{dni}/cuentas")
@ResponseStatus(HttpStatus.CREATED)
DTOCuenta altaCuenta(@PathVariable String dni) {
return new DTOCuenta(servicios.crearCuenta(dni));
}
/** Listar cuentas del cliente */
/**
* Listar cuentas del cliente
*/
@GetMapping("/clientes/{dni}/cuentas")
@ResponseStatus(HttpStatus.OK)
List<DTOCuenta> verCuentas(@PathVariable String dni) {
......@@ -126,7 +145,9 @@ public class ControladorREST {
.map(c -> new DTOCuenta(c)).toList();
}
/** Obtener una cuenta concreta */
/**
* Obtener una cuenta concreta
*/
@GetMapping("/clientes/{dni}/cuentas/{num}")
ResponseEntity<DTOCuenta> verCuenta(@PathVariable String dni, @PathVariable String num) {
return servicios.verCuentas(dni).stream()
......@@ -135,16 +156,18 @@ public class ControladorREST {
.map(c -> ResponseEntity.ok(new DTOCuenta(c)))
.orElse(ResponseEntity.notFound().build());
}
/** Registrar un nuevo movimiento en la cuenta */
/**
* Registrar un nuevo movimiento en la cuenta
*/
@PostMapping("/clientes/{dni}/cuentas/{numCuenta}/movimientos")
ResponseEntity<Void> registrarMovimiento(@PathVariable String dni, @PathVariable String numCuenta, @RequestBody DTOMovimiento movimiento) {
if (movimiento.tipo() == null) {
return ResponseEntity.badRequest().build();
}
try {
switch(movimiento.tipo()) {
switch (movimiento.tipo()) {
case DTOMovimiento.INGRESO:
servicios.ingreso(numCuenta, movimiento.numTarjeta(), movimiento.importe());
break;
......@@ -160,43 +183,42 @@ public class ControladorREST {
default:
return ResponseEntity.badRequest().build();
}
}
catch(SaldoInsuficienteParaOperacion e) {
} catch (SaldoInsuficienteParaOperacion e) {
return ResponseEntity.status(HttpStatus.PRECONDITION_FAILED).build();
}
catch(TarjetaNoRegistrada t) {
} catch (TarjetaNoRegistrada t) {
return ResponseEntity.status(HttpStatus.FAILED_DEPENDENCY).build();
}
return ResponseEntity.status(HttpStatus.CREATED).build();
}
/** Listar movimientos, acotados por fechas y paginados */
/**
* Listar movimientos, acotados por fechas y paginados
*/
@GetMapping("/clientes/{dni}/cuentas/{numCuenta}/movimientos")
ResponseEntity<List<DTOMovimiento>> verMovimientos(
@PathVariable String dni,
@PathVariable String dni,
@PathVariable String numCuenta,
@RequestParam(required=false) String desdeFecha,
@RequestParam(required=false) String hastaFecha,
@RequestParam(required=false, defaultValue="1") @Positive int pag,
@RequestParam(required=false, defaultValue="10") @Positive int num) {
@RequestParam(required = false) String desdeFecha,
@RequestParam(required = false) String hastaFecha,
@RequestParam(required = false, defaultValue = "1") @Positive int pag,
@RequestParam(required = false, defaultValue = "10") @Positive int num) {
LocalDateTime fechaInicial;
LocalDateTime fechaFinal;
LocalDateTime fechaFinal;
try {
fechaInicial = desdeFecha != null ? LocalDateTime.parse(desdeFecha) : null;
fechaFinal = hastaFecha != null ? LocalDateTime.parse(hastaFecha) : null;
}
catch(DateTimeParseException e) {
} catch (DateTimeParseException e) {
return ResponseEntity.badRequest().build();
}
List<Movimiento> movimientos = servicios.listarMovimientosCuentaDesdeHasta(numCuenta, fechaInicial, fechaFinal);
return ResponseEntity.ok(movimientos.stream()
.skip((pag - 1) * num)
.limit(num)
.map(m -> DTOMovimiento.dtoMovimiento(m))
.toList());
}
}
}
......@@ -26,18 +26,6 @@ public class ServicioDatosCliente implements UserDetailsService {
@Autowired
ServicioUjaCoin servicioUjaCoin;
/*
PasswordEncoder encoder;
public ServicioDatosCliente() {
encoder = new BCryptPasswordEncoder();
}
PasswordEncoder getEncoder() {
return encoder;
}
*/
@Override
public UserDetails loadUserByUsername(String dni) throws UsernameNotFoundException {
Cliente cliente = servicioUjaCoin.verCliente(dni)
......
......@@ -5,14 +5,14 @@
*/
package es.ujaen.dae.ujacoin.seguridad;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
/**
* Proveedor de datos de seguridad de UJaCoin
......@@ -20,25 +20,14 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
* @author ajrueda
*/
@Configuration
public class ServicioSeguridadUjaCoin extends WebSecurityConfigurerAdapter {
@Autowired
ServicioDatosCliente servicioDatosCliente;
public class ServicioSeguridadUjaCoin {
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
//@Autowired
//CacheManager cacheManager;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(servicioDatosCliente)
.passwordEncoder(new BCryptPasswordEncoder());
//.passwordEncoder(new CachedBCryptPasswordEncoder(cacheManager.getCache("claves")));
//auth.inMemoryAuthentication()
// .withUser("ujacoin").roles("CLIENTE").password("{noop}secret");
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
// Desactivar cualquier soporte de sesión
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
......@@ -47,11 +36,19 @@ public class ServicioSeguridadUjaCoin extends WebSecurityConfigurerAdapter {
// Activar seguridad HTTP Basic
httpSecurity.httpBasic();
// httpSecurity.authorizeRequests().antMatchers("/ujacoin/**").permitAll();
// Definir protección por URL
httpSecurity.authorizeRequests().antMatchers(HttpMethod.POST, "/ujacoin/clientes").permitAll();
// Permitir el acceso de un cliente sólo a sus recursos asociados (datos personales, cuentas, tarjetas, etc.)
httpSecurity.authorizeRequests().antMatchers("/ujacoin/clientes/{dni}/**").access("hasRole('CLIENTE') and #dni == principal.username");
}
return httpSecurity.build();
}
/** Hacer visible el gestor de autenticación del sistema por si se quiere hacer login manual */
// @Bean
// public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfiguration) throws Exception {
// return authConfiguration.getAuthenticationManager();
// }
}
......@@ -13,6 +13,7 @@ import java.time.LocalDate;
import java.util.List;
import javax.annotation.PostConstruct;
import org.assertj.core.api.Assertions;
import org.h2.security.auth.AuthenticationException;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
......@@ -22,6 +23,9 @@ import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
......@@ -33,7 +37,7 @@ import org.springframework.test.context.ActiveProfiles;
@SpringBootTest(classes = es.ujaen.dae.ujacoin.app.UjaCoinApp.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles(profiles = {"test"})
public class ControladorRESTTest {
@LocalServerPort
int localPort;
......@@ -53,7 +57,7 @@ public class ControladorRESTTest {
restTemplate = new TestRestTemplate(restTemplateBuilder);
}
/**
* Intento de creación de un cliente inválido
*/
......
package es.ujaen.dae.ujacoin.servicios;
import es.ujaen.dae.ujacoin.entidades.Cliente;
import es.ujaen.dae.ujacoin.entidades.Cuenta;
......@@ -8,6 +7,7 @@ import es.ujaen.dae.ujacoin.entidades.movimientos.Movimiento;
import es.ujaen.dae.ujacoin.entidades.movimientos.TransferenciaEmitida;
import es.ujaen.dae.ujacoin.entidades.movimientos.TransferenciaRecibida;
import es.ujaen.dae.ujacoin.excepciones.SaldoInsuficienteParaOperacion;
import es.ujaen.dae.ujacoin.servicios.ServicioUjaCoin;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
......@@ -21,10 +21,13 @@ import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.MethodMode;
import org.springframework.test.context.ActiveProfiles;
/**
* Test de integración de la aplicación
* @author ajrueda
......@@ -36,6 +39,7 @@ public class ServicioUjaCoinTest {
@Autowired
ServicioUjaCoin servicioUjaCoin;
@Test
public void testAccesoServicioUjaCoin() {
......
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