Ranghetti преди 7 месеца
родител
ревизия
64092cb800

+ 5 - 0
pom.xml

@@ -85,6 +85,11 @@
             <artifactId>spring-security-test</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>4.4.0</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 1 - 1
src/main/java/com/platform2easy/genesis/domain/repository/UserRepositoy.java → src/main/java/com/platform2easy/genesis/domain/repository/UserRepository.java

@@ -4,6 +4,6 @@ import com.platform2easy.genesis.domain.model.User;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.security.core.userdetails.UserDetails;
 
-public interface UserRepositoy extends JpaRepository<User,Long> {
+public interface UserRepository extends JpaRepository<User,Long> {
     UserDetails findByLogin(String login);
 }

+ 3 - 3
src/main/java/com/platform2easy/genesis/domain/service/CompraService.java

@@ -2,17 +2,17 @@ package com.platform2easy.genesis.domain.service;
 
 import com.platform2easy.genesis.domain.model.Compra;
 import com.platform2easy.genesis.domain.repository.CompraRepository;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 
 @Service
+@AllArgsConstructor
 public class CompraService {
 
-    @Autowired
-    private CompraRepository repository;
+    private final CompraRepository repository;
 
     @Transactional
     public void salvar(Compra compra) {

+ 5 - 5
src/main/java/com/platform2easy/genesis/domain/service/UserService.java

@@ -1,20 +1,20 @@
 package com.platform2easy.genesis.domain.service;
 
-import com.platform2easy.genesis.domain.repository.UserRepositoy;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.platform2easy.genesis.domain.repository.UserRepository;
+import lombok.AllArgsConstructor;
 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
+@AllArgsConstructor
 public class UserService implements UserDetailsService {
 
-    @Autowired
-    private UserRepositoy userRepositoy;
+    private final UserRepository userRepository;
 
     @Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
-        return userRepositoy.findByLogin(username);
+        return userRepository.findByLogin(username);
     }
 }

+ 4 - 3
src/main/java/com/platform2easy/genesis/security/config/SecurityConfiguration.java

@@ -1,6 +1,7 @@
 package com.platform2easy.genesis.security.config;
 
 
+import com.platform2easy.genesis.security.filter.AuthorizationFilter;
 import lombok.AllArgsConstructor;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -21,19 +22,19 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
 @AllArgsConstructor
 public class SecurityConfiguration {
 
-    //private AuthorizationFilter authorizationFilter;
+    private AuthorizationFilter authorizationFilter;
 
     @Bean
     public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
         return http
                 .csrf(AbstractHttpConfigurer::disable)
                 .cors(Customizer.withDefaults())
-                //.exceptionHandling(Customizer.withDefaults())
+                .exceptionHandling(Customizer.withDefaults())
                 .sessionManagement(sessionManagementConfigurer -> sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                 .authorizeHttpRequests(authorizationRegistry -> authorizationRegistry
                         .requestMatchers("/").permitAll()
                         .anyRequest().authenticated())
-                //.addFilterBefore(authorizationFilter, UsernamePasswordAuthenticationFilter.class)
+                .addFilterBefore(authorizationFilter, UsernamePasswordAuthenticationFilter.class)
                 .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.defaultSuccessUrl("/", true))
                 .logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.logoutSuccessUrl("/"))
                 .build();

+ 43 - 0
src/main/java/com/platform2easy/genesis/security/filter/AuthorizationFilter.java

@@ -0,0 +1,43 @@
+package com.platform2easy.genesis.security.filter;
+
+import com.platform2easy.genesis.domain.repository.UserRepository;
+import com.platform2easy.genesis.security.service.TokenService;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+@Component
+public class AuthorizationFilter extends OncePerRequestFilter {
+    @Autowired
+    TokenService tokenService;
+    @Autowired
+    UserRepository userRepository;
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+        var token = this.recoverToken(request);
+        if (token != null) {
+            var login = tokenService.validateToken(token);
+            UserDetails user = userRepository.findByLogin(login);
+
+            var authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
+            SecurityContextHolder.getContext().setAuthentication(authentication);
+        }
+        filterChain.doFilter(request, response);
+    }
+
+    private String recoverToken(HttpServletRequest request) {
+        var authHeader = request.getHeader("Authorization");
+        if (authHeader == null) return null;
+        return authHeader.replace("Bearer ", "");
+    }
+}

+ 50 - 0
src/main/java/com/platform2easy/genesis/security/service/TokenService.java

@@ -0,0 +1,50 @@
+package com.platform2easy.genesis.security.service;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTCreationException;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import com.platform2easy.genesis.domain.model.User;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+
+@Service
+public class TokenService {
+    @Value("${api.security.token.secret}")
+    private String secret;
+
+    public String generateToken(User user) {
+        try {
+            var algorithm = Algorithm.HMAC256(secret);
+            return JWT.create()
+                    .withIssuer("auth-api")
+                    .withSubject(user.getLogin())
+                    .withExpiresAt(genExpirationDate())
+                    .sign(algorithm);
+        } catch (JWTCreationException exception) {
+            throw new RuntimeException("Error while generating token", exception);
+        }
+    }
+
+    public String validateToken(String token) {
+        try {
+            var algorithm = Algorithm.HMAC256(secret);
+            return JWT.require(algorithm)
+                    .withIssuer("auth-api")
+                    .build()
+                    .verify(token)
+                    .getSubject();
+        } catch (JWTVerificationException exception) {
+            return "";
+        }
+    }
+
+    private Instant genExpirationDate() {
+        return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));
+    }
+}

+ 21 - 0
src/main/java/com/platform2easy/genesis/web/api/AuthenticationController.java

@@ -1,12 +1,33 @@
 package com.platform2easy.genesis.web.api;
 
+import com.platform2easy.genesis.domain.model.User;
+import com.platform2easy.genesis.security.service.TokenService;
+import com.platform2easy.genesis.web.dto.authentication.AuthenticationDTO;
+import com.platform2easy.genesis.web.dto.authentication.LoginResponseDTO;
+import jakarta.validation.Valid;
+import lombok.AllArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 @RestController
 @RequestMapping("authentication")
+@AllArgsConstructor
 public class AuthenticationController {
 
+    private final AuthenticationManager authenticationManager;
+    private final TokenService tokenService;
 
+    @PostMapping("/login")
+    public ResponseEntity login(@RequestBody @Valid AuthenticationDTO data) {
+        var usernamePassword = new UsernamePasswordAuthenticationToken(data.login(), data.password());
+        var auth = this.authenticationManager.authenticate(usernamePassword);
+        var token = tokenService.generateToken((User) auth.getPrincipal());
+        return ResponseEntity.ok(new LoginResponseDTO(token));
+    }
 
 }

+ 3 - 3
src/main/java/com/platform2easy/genesis/web/controller/CompraController.java

@@ -3,7 +3,7 @@ package com.platform2easy.genesis.web.controller;
 import com.platform2easy.genesis.domain.model.Compra;
 import com.platform2easy.genesis.domain.model.ItemCompra;
 import com.platform2easy.genesis.domain.service.CompraService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -15,10 +15,10 @@ import java.util.Arrays;
 
 @Controller
 @RequestMapping("compra")
+@AllArgsConstructor
 public class CompraController {
 
-    @Autowired
-    private CompraService service;
+    private final CompraService service;
 
     @GetMapping()
     public String iniciar(Compra compra, Model model) {

+ 4 - 0
src/main/java/com/platform2easy/genesis/web/dto/authentication/AuthenticationDTO.java

@@ -0,0 +1,4 @@
+package com.platform2easy.genesis.web.dto.authentication;
+
+public record AuthenticationDTO(String login, String password) {
+}

+ 4 - 0
src/main/java/com/platform2easy/genesis/web/dto/authentication/LoginResponseDTO.java

@@ -0,0 +1,4 @@
+package com.platform2easy.genesis.web.dto.authentication;
+
+public record LoginResponseDTO(String token) {
+}