diff --git a/src/main/java/com/jwtauthcruddemo/configs/JWTAuthFilter.java b/src/main/java/com/jwtauthcruddemo/configs/JWTAuthFilter.java new file mode 100644 index 0000000..6ff2808 --- /dev/null +++ b/src/main/java/com/jwtauthcruddemo/configs/JWTAuthFilter.java @@ -0,0 +1,52 @@ +package com.jwtauthcruddemo.configs; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpHeaders; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.Objects; + +/*** + * Classe de configuração HTTP para interceptar + * as solicitações recebidas e validar o JWT + */ +public class JWTAuthFilter extends OncePerRequestFilter { + + private final LoginAuthProvider loginAuthProvider; + + public JWTAuthFilter(LoginAuthProvider loginAuthProvider) { + this.loginAuthProvider = loginAuthProvider; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + + // Verificar se existe um cabeçalho de autorização + String header = request.getHeader(HttpHeaders.AUTHORIZATION); + + // Portador + if (Objects.nonNull(header)) validateAndSetAuthentication(header); + + // Continue a cadeia de filtros + filterChain.doFilter(request, response); + } + + private void validateAndSetAuthentication(String header) { + String[] authElements = header.split(" "); + if (authElements.length == 2 && "Bearer".equals(authElements[0])) { + try { + SecurityContextHolder.getContext().setAuthentication(loginAuthProvider.validateToken(authElements[1])); + } catch (RuntimeException ex) { + SecurityContextHolder.clearContext(); + throw ex; + } + } + } +} diff --git a/src/main/java/com/jwtauthcruddemo/configs/LoginAuthProvider.java b/src/main/java/com/jwtauthcruddemo/configs/LoginAuthProvider.java index 2aaf489..4cefffd 100644 --- a/src/main/java/com/jwtauthcruddemo/configs/LoginAuthProvider.java +++ b/src/main/java/com/jwtauthcruddemo/configs/LoginAuthProvider.java @@ -22,7 +22,7 @@ public class LoginAuthProvider { private static final int TIME_TO_EXPIRED_TOKEN = 1; // 1 Hour - @Value("{security.jwt.token.secret-key:secret-key}") + @Value("${security.jwt.token.secret-key:secret-key}") private String secretKey; @PostConstruct @@ -33,7 +33,6 @@ protected void init() { public String createToken(UserDto userDto) { var validity = Date.from(Instant.now().plus(TIME_TO_EXPIRED_TOKEN, ChronoUnit.HOURS)); - return JWT.create() .withIssuer(userDto.getLogin()) .withIssuedAt(new Date()) @@ -41,7 +40,6 @@ public String createToken(UserDto userDto) { .withClaim("firstName", userDto.getFirstName()) .withClaim("lastName", userDto.getLastName()) .sign(Algorithm.HMAC256(secretKey)); - } public Authentication validateToken(String token) { @@ -56,6 +54,7 @@ public Authentication validateToken(String token) { return new UsernamePasswordAuthenticationToken(userDto, null, Collections.emptyList()); } + /* Usando as informações do JWT para criar um usuario DTO */ private static UserDto getUserDtoFromDecodedJWT(DecodedJWT decodedJWT) { var userDto = new UserDto(); userDto.setLogin(decodedJWT.getIssuer()); @@ -63,4 +62,5 @@ private static UserDto getUserDtoFromDecodedJWT(DecodedJWT decodedJWT) { userDto.setLastName(decodedJWT.getClaim("lastName").asString()); return userDto; } + } diff --git a/src/main/java/com/jwtauthcruddemo/configs/SecurityConfig.java b/src/main/java/com/jwtauthcruddemo/configs/SecurityConfig.java index 30800db..698b006 100644 --- a/src/main/java/com/jwtauthcruddemo/configs/SecurityConfig.java +++ b/src/main/java/com/jwtauthcruddemo/configs/SecurityConfig.java @@ -10,14 +10,23 @@ import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; @Configuration @EnableWebSecurity public class SecurityConfig { + private final LoginAuthProvider loginAuthProvider; + + public SecurityConfig(LoginAuthProvider loginAuthProvider) { + this.loginAuthProvider = loginAuthProvider; + } + @Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { httpSecurity.csrf(AbstractHttpConfigurer::disable) + // Filtro antes do filtro de autenticação básico, porque o JWTAuthFilter desejo que seja primeiro filtro. + .addFilterBefore(new JWTAuthFilter(loginAuthProvider), BasicAuthenticationFilter.class) .sessionManagement(SecurityConfig::configSessionManagement) .authorizeHttpRequests(SecurityConfig::configAuthorizeHttpRequests); diff --git a/src/main/java/com/jwtauthcruddemo/controllers/AuthController.java b/src/main/java/com/jwtauthcruddemo/controllers/AuthController.java index ff59f55..99a2dde 100644 --- a/src/main/java/com/jwtauthcruddemo/controllers/AuthController.java +++ b/src/main/java/com/jwtauthcruddemo/controllers/AuthController.java @@ -1,5 +1,6 @@ package com.jwtauthcruddemo.controllers; +import com.jwtauthcruddemo.configs.LoginAuthProvider; import com.jwtauthcruddemo.dtos.input.CredentialsDto; import com.jwtauthcruddemo.dtos.input.SignUpDto; import com.jwtauthcruddemo.dtos.output.UserDto; @@ -17,20 +18,24 @@ public class AuthController { private final UserService userService; + private final LoginAuthProvider loginAuthProvider; - public AuthController(UserService userService) { + public AuthController(UserService userService, LoginAuthProvider loginAuthProvider) { this.userService = userService; + this.loginAuthProvider = loginAuthProvider; } @PostMapping("/login") public ResponseEntity login(@RequestBody CredentialsDto credentialsDto) { UserDto userDto = userService.login(credentialsDto); + userDto.setToken(loginAuthProvider.createToken(userDto)); return ResponseEntity.ok(userDto); } @PostMapping("/register") public ResponseEntity register(@RequestBody SignUpDto signUpDto) { UserDto userDto = userService.register(signUpDto); + userDto.setToken(loginAuthProvider.createToken(userDto)); return ResponseEntity.created(URI.create("/users/" + userDto.getId())).body(userDto); } }