- 토큰 검증 추가

- 각 스키마 정보 추가
This commit is contained in:
Hyojin Ahn 2026-06-04 15:42:10 -04:00
parent 68233402fc
commit 6bb2817654
9 changed files with 70 additions and 26 deletions

View File

@ -4,8 +4,13 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import com.goi.erp.employee.EmployeeDetails;
import java.io.IOException; import java.io.IOException;
@RestController @RestController
@ -46,4 +51,33 @@ public class AuthenticationController {
authenticationService.authenticateSystem(request) authenticationService.authenticateSystem(request)
); );
} }
@GetMapping("/me")
public AuthenticationResponse me() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null ||
!authentication.isAuthenticated() ||
authentication instanceof AnonymousAuthenticationToken) {
return AuthenticationResponse.builder()
.authenticated(false)
.build();
}
EmployeeDetails principal = (EmployeeDetails) authentication.getPrincipal();
return AuthenticationResponse.builder()
.authenticated(true)
.loginId(principal.getUsername())
.firstName(principal.getEmployee().getEmpFirstName())
.lastName(principal.getEmployee().getEmpLastName())
.roles(
principal.getAuthorities().stream()
.map(a -> a.getAuthority())
.toList()
)
.build();
}
} }

View File

@ -14,6 +14,7 @@ import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import com.goi.erp.auth.AuthCookieService; import com.goi.erp.auth.AuthCookieService;
import com.goi.erp.token.TokenRepository;
import java.io.IOException; import java.io.IOException;
import java.util.Optional; import java.util.Optional;
@ -25,6 +26,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtService jwtService; private final JwtService jwtService;
private final UserDetailsService userDetailsService; private final UserDetailsService userDetailsService;
private final AuthCookieService authCookieService; private final AuthCookieService authCookieService;
private final TokenRepository tokenRepository;
@Override @Override
protected void doFilterInternal( protected void doFilterInternal(
@ -39,7 +41,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
} }
String jwt = resolveToken(request); String jwt = resolveToken(request);
if (jwt == null) { if (jwt == null) {
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
return; return;
@ -55,11 +56,22 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
UserDetails userDetails = userDetailsService.loadUserByUsername(username); UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 1. JWT 자체 유효성
if (!jwtService.isTokenValid(jwt, userDetails)) { if (!jwtService.isTokenValid(jwt, userDetails)) {
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
return; return;
} }
// 2. DB 토큰 상태 확인
boolean isTokenActive = tokenRepository
.findByToken(jwt)
.map(t -> !t.isExpired() && !t.isRevoked())
.orElse(false);
if (!isTokenActive) {
filterChain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken( new UsernamePasswordAuthenticationToken(
userDetails, userDetails,
@ -82,10 +94,10 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
*/ */
private String resolveToken(HttpServletRequest request) { private String resolveToken(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization"); // String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) { // if (authHeader != null && authHeader.startsWith("Bearer ")) {
return authHeader.substring(7); // return authHeader.substring(7);
} // }
Optional<String> cookieToken = authCookieService.extractJwt(request); Optional<String> cookieToken = authCookieService.extractJwt(request);
return cookieToken.orElse(null); return cookieToken.orElse(null);

View File

@ -62,7 +62,11 @@ public class SecurityConfiguration {
public CorsConfigurationSource corsConfigurationSource() { public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration(); CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("http://localhost:5173")); config.setAllowedOriginPatterns(List.of(
"http://localhost:5173",
"http://192.168.*.*:5173",
"http://10.*.*.*:5173"
));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowedHeaders(List.of("Authorization", "Content-Type", "X-CSRF-TOKEN")); config.setAllowedHeaders(List.of("Authorization", "Content-Type", "X-CSRF-TOKEN"));
config.setAllowCredentials(true); config.setAllowCredentials(true);

View File

@ -2,8 +2,6 @@ package com.goi.erp.employee;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import java.util.UUID; import java.util.UUID;
@ -14,36 +12,32 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@Entity @Entity
@Table(name = "employee") @Table(schema="hcm", name = "vw_auth_employee")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Builder @Builder
public class Employee { public class Employee {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "emp_id") @Column(name = "emp_id")
private Long empId; // 내부 PK, 외부 노출 X private Long empId;
@Column(name = "emp_uuid", unique = true, nullable = false) @Column(name = "emp_uuid")
private UUID empUuid; // 외부 키로 사용 private UUID empUuid;
@Column(name = "emp_login_id", unique = true, nullable = false) @Column(name = "emp_login_id")
private String empLoginId; private String empLoginId;
@Column(name = "emp_login_password", nullable = false) @Column(name = "emp_login_password")
private String empLoginPassword; private String empLoginPassword;
@Column(name = "emp_status")
private String empStatus;
@Column(name = "emp_first_name") @Column(name = "emp_first_name")
private String empFirstName; private String empFirstName;
@Column(name = "emp_last_name") @Column(name = "emp_last_name")
private String empLastName; private String empLastName;
@Column(name = "emp_dept_id")
private Long empDeptId;
@Column(name = "emp_status", columnDefinition = "CHAR(1)")
private String empStatus;
} }

View File

@ -21,7 +21,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@Entity @Entity
@Table(name = "employee_role") @Table(schema="auth", name = "employee_role")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor

View File

@ -16,7 +16,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@Entity @Entity
@Table(name = "permission_info", @Table(schema="auth", name = "permission_info",
uniqueConstraints = @UniqueConstraint(columnNames = {"perm_module", "perm_action", "perm_scope"})) uniqueConstraints = @UniqueConstraint(columnNames = {"perm_module", "perm_action", "perm_scope"}))
@Data @Data
@NoArgsConstructor @NoArgsConstructor

View File

@ -19,7 +19,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@Entity @Entity
@Table(name = "role_info") @Table(schema="auth", name = "role_info")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor

View File

@ -18,7 +18,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@Entity @Entity
@Table(name = "role_permission") @Table(schema="auth", name = "role_permission")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor

View File

@ -19,7 +19,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@Entity @Entity
@Table(name = "employee_token") @Table(schema="auth", name = "employee_token")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor