From 0f1e5a5d8871e8e4caff06a03ab38e1f5916bc73 Mon Sep 17 00:00:00 2001 From: Marc0Franc0 Date: Sun, 13 Aug 2023 11:38:48 -0300 Subject: [PATCH] Update v1.2.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -Documentación con OpenApi -Modifiación en la autenticación --- README.md | 4 ++- pom.xml | 7 ++++- .../app/config/SpringDocConfiguration.java | 28 +++++++++++++++++++ .../com/app/controller/AdminController.java | 2 ++ .../java/com/app/controller/Controller.java | 12 ++++++-- src/main/java/com/app/dto/LoginDTO.java | 16 +++++++++++ .../java/com/app/exception/SQLException.java | 2 +- .../java/com/app/security/SecurityConfig.java | 6 +++- .../com/app/service/UserEntityService.java | 2 ++ .../app/service/UserEntityServiceImpl.java | 13 +++++++++ src/main/resources/application.properties | 13 +++++++++ src/main/resources/application.yml | 17 ----------- 12 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/app/config/SpringDocConfiguration.java create mode 100644 src/main/java/com/app/dto/LoginDTO.java create mode 100644 src/main/resources/application.properties delete mode 100644 src/main/resources/application.yml diff --git a/README.md b/README.md index 31d2f06..66b8c09 100644 --- a/README.md +++ b/README.md @@ -46,4 +46,6 @@ mvn clean install mvn spring-boot:run ``` -Dirigirse a: [http://localhost:8080/](http://localhost:8080/) \ No newline at end of file +Dirigirse a: +- [http://localhost:8080/](http://localhost:8080/) +- [http://localhost:8080/swagger-ui/index.html](http://localhost:8080/swagger-ui/index.html) \ No newline at end of file diff --git a/pom.xml b/pom.xml index b468a0f..b641f0d 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.app User-Api-Jwt - 1.2.0 + 1.2.1 User-Api-Jwt Proyecto de muestra sobre cómo implementar la seguridad con JWT basada en Spring boot 3 y Spring security 6 @@ -72,6 +72,11 @@ jakarta.validation-api 3.0.2 + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.1.0 + diff --git a/src/main/java/com/app/config/SpringDocConfiguration.java b/src/main/java/com/app/config/SpringDocConfiguration.java new file mode 100644 index 0000000..bb57649 --- /dev/null +++ b/src/main/java/com/app/config/SpringDocConfiguration.java @@ -0,0 +1,28 @@ +package com.app.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityScheme; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +@Configuration +public class SpringDocConfiguration { + //Bean para la configuración JWT en los endpoints de la documentación + @Bean + public OpenAPI customOpenApi(){ + return new OpenAPI() + .info(new Info() + .title("User-Api-Jwt") + .version("1.2.1") + .description("Proyecto de muestra sobre cómo implementar la seguridad con\n" + + "\t\tJWT basada en Spring boot 3 y Spring security 6")) + .components(new Components() + .addSecuritySchemes("Bearer Authentication", + new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT"))); + } + +} diff --git a/src/main/java/com/app/controller/AdminController.java b/src/main/java/com/app/controller/AdminController.java index 2bbbf2f..30a5d3b 100644 --- a/src/main/java/com/app/controller/AdminController.java +++ b/src/main/java/com/app/controller/AdminController.java @@ -2,6 +2,7 @@ import com.app.dto.RegisterDTO; import com.app.service.UserEntityService; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -12,6 +13,7 @@ @RestController @RequestMapping("private") +@SecurityRequirement(name="Bearer Authentication") public class AdminController { @Autowired UserEntityService userEntityService; diff --git a/src/main/java/com/app/controller/Controller.java b/src/main/java/com/app/controller/Controller.java index 2753e59..4ec2635 100644 --- a/src/main/java/com/app/controller/Controller.java +++ b/src/main/java/com/app/controller/Controller.java @@ -1,7 +1,9 @@ package com.app.controller; +import com.app.dto.LoginDTO; import com.app.dto.RegisterDTO; import com.app.service.UserEntityService; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -11,16 +13,22 @@ import java.util.Set; @RestController -@RequestMapping("public") +@RequestMapping("public/auth") +@SecurityRequirement(name="Bearer Authentication") public class Controller { @Autowired UserEntityService userEntityService; //Endpoint para poder registrarse y tener acceso - @PostMapping("/auth/register") + @PostMapping("/register") public ResponseEntity register(@Valid @RequestBody RegisterDTO registerDTO){ RegisterDTO user = registerDTO; user.getRoles().clear(); user.setRoles(Set.of("USER")); return ResponseEntity.status(HttpStatus.OK).body(userEntityService.registerUser(registerDTO)); } + @PostMapping("/login") + public void authenticate(@Valid @RequestBody LoginDTO loginDTO){ + LoginDTO user = loginDTO; + userEntityService.authenticate(loginDTO); + } } diff --git a/src/main/java/com/app/dto/LoginDTO.java b/src/main/java/com/app/dto/LoginDTO.java new file mode 100644 index 0000000..758ce88 --- /dev/null +++ b/src/main/java/com/app/dto/LoginDTO.java @@ -0,0 +1,16 @@ +package com.app.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Builder +@Getter +@Setter +public class LoginDTO { + @NotBlank(message = "username no debe estar vacío") + private String username; + @NotBlank(message = "password no debe estar vacío") + private String password; +} diff --git a/src/main/java/com/app/exception/SQLException.java b/src/main/java/com/app/exception/SQLException.java index 713e45e..949d421 100644 --- a/src/main/java/com/app/exception/SQLException.java +++ b/src/main/java/com/app/exception/SQLException.java @@ -17,7 +17,7 @@ public class SQLException { @ExceptionHandler(SQLIntegrityConstraintViolationException.class) public ResponseEntity captureSQLIntegrityConstraintViolationException (SQLIntegrityConstraintViolationException e){ - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Message: ".concat(e.getMessage())); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Message: ".concat("Pruebe con otro username")); } } diff --git a/src/main/java/com/app/security/SecurityConfig.java b/src/main/java/com/app/security/SecurityConfig.java index 03e5950..e00e361 100644 --- a/src/main/java/com/app/security/SecurityConfig.java +++ b/src/main/java/com/app/security/SecurityConfig.java @@ -69,8 +69,12 @@ SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationManager .authorizeHttpRequests( //Configuración de acceso a los endpoints auth-> { - //endpoint para poder registrarse por primera vez + //Endpoint de documentación + auth.requestMatchers + ("/swagger-ui.html","/v3/api-docs/**","/swagger-ui/**").permitAll(); + //endpoint para poder registrarse por primera vez y autenticarse auth.requestMatchers("/public/auth/register").permitAll(); + auth.requestMatchers("/public/auth/login").permitAll(); //endpoint público con acceso para usuarios y administradores auth.requestMatchers("/public/**").hasAnyRole("USER","ADMIN"); //endpoint privado con acceso solo para administradores diff --git a/src/main/java/com/app/service/UserEntityService.java b/src/main/java/com/app/service/UserEntityService.java index ea53f09..77247d4 100644 --- a/src/main/java/com/app/service/UserEntityService.java +++ b/src/main/java/com/app/service/UserEntityService.java @@ -1,5 +1,6 @@ package com.app.service; +import com.app.dto.LoginDTO; import com.app.dto.RegisterDTO; import com.app.model.UserEntity; import org.springframework.security.core.userdetails.User; @@ -7,4 +8,5 @@ public interface UserEntityService { public UserEntity registerUser(RegisterDTO registerDTO); public User createUserSecurity(UserEntity userEntity); + public void authenticate(LoginDTO loginDTO); } diff --git a/src/main/java/com/app/service/UserEntityServiceImpl.java b/src/main/java/com/app/service/UserEntityServiceImpl.java index c2d3a99..0acc31c 100644 --- a/src/main/java/com/app/service/UserEntityServiceImpl.java +++ b/src/main/java/com/app/service/UserEntityServiceImpl.java @@ -1,11 +1,14 @@ package com.app.service; +import com.app.dto.LoginDTO; import com.app.dto.PersonalData; import com.app.dto.RegisterDTO; import com.app.model.ERole; import com.app.model.RoleEntity; import com.app.model.UserEntity; import com.app.repository.UserRepository; +import com.app.security.jwt.JwtAuthenticationFilter; +import com.app.security.jwt.JwtTokenProvider; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.User; @@ -20,6 +23,8 @@ public class UserEntityServiceImpl implements UserEntityService{ UserRepository userRepository; @Autowired PasswordEncoder passwordEncoder; + @Autowired + JwtTokenProvider jwtTokenProvider; //Método para registrar un usuario nuevo public UserEntity registerUser(RegisterDTO registerDTO){ Set roles = @@ -61,4 +66,12 @@ public User createUserSecurity(UserEntity userEntity){ userEntity.getAuthorities() ); } + + @Override + public void authenticate(LoginDTO loginDTO) { + JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(jwtTokenProvider); + //Se envia al filtro creado el usernmae y password del usuario que desea autenticarse + jwtAuthenticationFilter.setUsernameParameter(loginDTO.getUsername()); + jwtAuthenticationFilter.setPasswordParameter(loginDTO.getPassword()); + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..ba22711 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,13 @@ +#Configuración base de datos +spring.datasource.url: ${SPRING_DATASOURCE_URL} +spring.datasource.username: ${SPRING_DATASOURCE_USERNAME} +spring.datasource.password: ${SPRING_DATASOURCE_PASSWORD} +spring.datasource.jpa.hibernate.ddl-auto: ${SPRING_JPA_HIBERNATE_DDL_AUTO} + +#Configuración usuario administrador +user.admin.username: ${USER_ADMIN_USERNAME} +user.admin.password: ${USER_ADMIN_PASSWORD} + +#Configuración JWT +jwt.secret.key: ${JWT_SECRET_KEY} +jwt.secret.time.expiration: ${JWT_TIME_EXPIRATION} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml deleted file mode 100644 index ebbaec1..0000000 --- a/src/main/resources/application.yml +++ /dev/null @@ -1,17 +0,0 @@ -spring: - datasource: - url: ${SPRING_DATASOURCE_URL} - username: ${SPRING_DATASOURCE_USERNAME} - password: ${SPRING_DATASOURCE_PASSWORD} -user: - admin: - username: ${USER_ADMIN_USERNAME} - password: ${USER_ADMIN_PASSWORD} - jpa: - hibernate: - ddl-auto: ${SPRING_JPA_HIBERNATE_DDL_AUTO} -jwt: - secret: - key: ${JWT_SECRET_KEY} - time: - expiration: ${JWT_TIME_EXPIRATION}