dużo lepsza autoryzacja teraz, dużo lepsza. Tokeny wygasają, można mieć tylko jeden aktywny token per user
This commit is contained in:
@@ -27,7 +27,6 @@ public class SecurityConfig {
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/api/v1/auth/**").permitAll()
|
||||
.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated())
|
||||
.sessionManagement(session -> session
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
|
||||
|
||||
@@ -5,6 +5,7 @@ import _11.asktpk.artisanconnectbackend.entities.Client;
|
||||
import _11.asktpk.artisanconnectbackend.security.JwtUtil;
|
||||
import _11.asktpk.artisanconnectbackend.service.ClientService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -12,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/auth")
|
||||
public class AuthController {
|
||||
@@ -33,6 +35,7 @@ public class AuthController {
|
||||
|
||||
String token = jwtUtil.generateToken(client.getEmail(), userRole, userId);
|
||||
|
||||
log.info("Logged in as " + client.getEmail());
|
||||
return ResponseEntity.status(HttpStatus.OK)
|
||||
.body(new AuthResponseDTO(userId, userRole, token));
|
||||
} else {
|
||||
@@ -54,6 +57,8 @@ public class AuthController {
|
||||
savedClient.getId()
|
||||
);
|
||||
|
||||
log.info("Registered as " + savedClient.getEmail());
|
||||
|
||||
return ResponseEntity.status(HttpStatus.CREATED)
|
||||
.body(new AuthResponseDTO(
|
||||
savedClient.getId(),
|
||||
|
||||
@@ -36,8 +36,12 @@ public class JwtRequestFilter extends OncePerRequestFilter {
|
||||
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
|
||||
jwt = authorizationHeader.substring(7);
|
||||
|
||||
if (jwtUtil.isBlacklisted(jwt)) {
|
||||
if (jwtUtil.isBlacklisted(jwt) || !jwtUtil.isLatestToken(jwt)) {
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType("application/json");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
String jsonResponse = "{\"error\": \"Token is invalid or expired. Please login again.\"}";
|
||||
response.getWriter().write(jsonResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -40,11 +37,27 @@ public class JwtUtil {
|
||||
return Keys.hmacShaKeyFor(secret.getBytes());
|
||||
}
|
||||
|
||||
private final Map<String, String> userActiveTokens = new ConcurrentHashMap<>();
|
||||
|
||||
public boolean isLatestToken(String token) {
|
||||
String email = extractEmail(token);
|
||||
String tokenId = extractTokenId(token);
|
||||
String latestTokenId = userActiveTokens.get(email);
|
||||
|
||||
return latestTokenId != null && latestTokenId.equals(tokenId);
|
||||
}
|
||||
|
||||
public String generateToken(String email, String role, Long userId) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("role", role);
|
||||
claims.put("userId", userId);
|
||||
return createToken(claims, email);
|
||||
claims.put("tokenId", UUID.randomUUID().toString());
|
||||
|
||||
String token = createToken(claims, email);
|
||||
|
||||
userActiveTokens.put(email, extractTokenId(token));
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
private String createToken(Map<String, Object> claims, String subject) {
|
||||
@@ -57,6 +70,10 @@ public class JwtUtil {
|
||||
.compact();
|
||||
}
|
||||
|
||||
public String extractTokenId(String token) {
|
||||
return extractAllClaims(token).get("tokenId", String.class);
|
||||
}
|
||||
|
||||
public String extractEmail(String token) {
|
||||
return extractClaim(token, Claims::getSubject);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user