Commit de6e3ef3 by Antonio Rueda

Autenticación básica HTTP mediante Spring Security para acceso al API.

parent 9e6ce320
...@@ -34,6 +34,11 @@ ...@@ -34,6 +34,11 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
......
...@@ -11,7 +11,8 @@ import org.springframework.boot.autoconfigure.domain.EntityScan; ...@@ -11,7 +11,8 @@ import org.springframework.boot.autoconfigure.domain.EntityScan;
@SpringBootApplication(scanBasePackages={ @SpringBootApplication(scanBasePackages={
"es.ujaen.dae.ujacoin.servicios", "es.ujaen.dae.ujacoin.servicios",
"es.ujaen.dae.ujacoin.repositorios", "es.ujaen.dae.ujacoin.repositorios",
"es.ujaen.dae.ujacoin.controladoresREST" "es.ujaen.dae.ujacoin.controladoresREST",
"es.ujaen.dae.ujacoin.seguridad"
}) })
@EntityScan(basePackages="es.ujaen.dae.ujacoin.entidades") @EntityScan(basePackages="es.ujaen.dae.ujacoin.entidades")
public class UjaCoinApp { public class UjaCoinApp {
......
...@@ -74,8 +74,8 @@ public class ControladorREST { ...@@ -74,8 +74,8 @@ public class ControladorREST {
/** 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}") @GetMapping("/clientes/{dni}")
ResponseEntity<DTOCliente> loginCliente(@PathVariable String dni, @RequestParam String clave) { ResponseEntity<DTOCliente> verCliente(@PathVariable String dni) {
Optional<Cliente> cliente = servicios.loginCliente(dni, clave); Optional<Cliente> cliente = servicios.verCliente(dni);
return cliente return cliente
.map(c -> ResponseEntity.ok(new DTOCliente(c))) .map(c -> ResponseEntity.ok(new DTOCliente(c)))
.orElse(ResponseEntity.notFound().build()); .orElse(ResponseEntity.notFound().build());
......
package es.ujaen.dae.ujacoin.entidades; package es.ujaen.dae.ujacoin.entidades;
import es.ujaen.dae.ujacoin.util.ExprReg; import es.ujaen.dae.ujacoin.util.ExprReg;
import es.ujaen.dae.ujacoin.util.CodificadorMd5; import es.ujaen.dae.ujacoin.util.CodificadorPassword;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -80,7 +80,8 @@ public class Cliente implements Serializable { ...@@ -80,7 +80,8 @@ public class Cliente implements Serializable {
this.tlf = tlf; this.tlf = tlf;
this.email = email; this.email = email;
this.clave = (clave != null ? CodificadorMd5.codificar(clave) : null); this.clave = (clave != null ? CodificadorPassword.codificar(clave) : null);
// this.clave = clave;
tarjetas = new ArrayList<>(); tarjetas = new ArrayList<>();
cuentas = new ArrayList<>(); cuentas = new ArrayList<>();
...@@ -116,7 +117,12 @@ public class Cliente implements Serializable { ...@@ -116,7 +117,12 @@ public class Cliente implements Serializable {
* @return * @return
*/ */
public boolean claveValida(String clave) { public boolean claveValida(String clave) {
return this.clave.equals(CodificadorMd5.codificar(clave)); return CodificadorPassword.igual(clave, this.clave);
//return this.clave.equals(clave);
}
public String getClave() {
return clave;
} }
/** /**
......
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package es.ujaen.dae.ujacoin.seguridad;
import es.ujaen.dae.ujacoin.entidades.Cliente;
import es.ujaen.dae.ujacoin.servicios.ServicioUjaCoin;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
/**
* Servicio que proporciona los datos del cliente
* @author ajrueda
*/
@Service
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)
.orElseThrow(() -> new UsernameNotFoundException(""));
return User.withUsername(cliente.getDni())
.roles("CLIENTE").password(cliente.getClave())
.build();
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package es.ujaen.dae.ujacoin.seguridad;
import org.springframework.beans.factory.annotation.Autowired;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* Proveedor de datos de seguridad de UJaCoin
*
* @author ajrueda
*/
@Configuration
@EnableWebSecurity
public class ServicioSeguridadUjaCoin extends WebSecurityConfigurerAdapter {
@Autowired
ServicioDatosCliente servicioDatosCliente;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(servicioDatosCliente)
.passwordEncoder(new BCryptPasswordEncoder());
// auth.inMemoryAuthentication()
// .withUser("ujacoin").roles("CLIENTE").password("{noop}secret");
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable();
httpSecurity.httpBasic();
httpSecurity.authorizeRequests().antMatchers(HttpMethod.POST, "/ujacoin/clientes").anonymous();
// 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");
}
}
...@@ -83,6 +83,21 @@ public class ServicioUjaCoin { ...@@ -83,6 +83,21 @@ public class ServicioUjaCoin {
} }
/** /**
* Realiza un login de un cliente
* @param dni el DNI del cliente
* @param clave la clave de acceso
* @return el objeto de la clase Cliente asociado
*/
@Transactional
public Optional<Cliente> verCliente(@NotBlank String dni) {
Optional<Cliente> clienteLogin = repositorioClientes.buscar(dni);
// Asegurarnos de que se devuelve el cliente con los datos precargados
clienteLogin.ifPresent(c -> c.verCuentas().size());
return clienteLogin;
}
/**
* Crear una cuenta adicional para el cliente * Crear una cuenta adicional para el cliente
* @param dni el DNI delcliente * @param dni el DNI delcliente
* @return la cuenta creada * @return la cuenta creada
......
package es.ujaen.dae.ujacoin.util; package es.ujaen.dae.ujacoin.util;
import java.security.MessageDigest; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
/** /**
* Codificador sencillo para contraseñas basado en Md5 (no seguro) * Codificador sencillo para contraseñas basado en Md5 (no seguro)
* @author ajrueda * @author ajrueda
*/ */
public class CodificadorMd5 { public class CodificadorPassword {
static BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
private CodificadorMd5() { private CodificadorPassword() {
} }
public static String codificar(String cadena) { public static String codificar(String cadena) {
/*
String cadenaCodificada = null; String cadenaCodificada = null;
try { try {
...@@ -25,6 +26,11 @@ public class CodificadorMd5 { ...@@ -25,6 +26,11 @@ public class CodificadorMd5 {
// No debe ocurrir puesto que MD5 es un algoritmo que existe en la // No debe ocurrir puesto que MD5 es un algoritmo que existe en la
// implementación Java estándar // implementación Java estándar
} }
return cadenaCodificada; */
return encoder.encode(cadena);
}
public static boolean igual(String password, String passwordCodificado) {
return encoder.matches(password, passwordCodificado);
} }
} }
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