crm-rest-api/src/main/java/com/goi/erp/token/ApplicationAuditAware.java

86 lines
2.9 KiB
Java

package com.goi.erp.token;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.data.domain.AuditorAware;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import jakarta.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
/**
* auth-service에서 발급한 JWT 토큰 기반으로 현재 사용자(empId)를 가져오는 AuditorAware 구현체
*
* - JPA auditing에서 사용자가 누군지 기록할 때 사용
* - SecurityContextHolder 없이도 동작 가능
* - HttpServletRequest에서 Authorization 헤더를 읽어 토큰 파싱
*/
public class ApplicationAuditAware implements AuditorAware<Integer> {
private final String jwtSecret;
public ApplicationAuditAware(String jwtSecret) {
this.jwtSecret = jwtSecret;
}
/**
* 현재 요청을 수행하는 사용자의 empId 반환
* @return Optional<Integer> - empId가 없거나 토큰이 유효하지 않으면 Optional.empty()
*/
@Override
public Optional<Integer> getCurrentAuditor() {
HttpServletRequest request = getCurrentHttpRequest();
if (request == null) {
return Optional.empty();
}
String token = resolveToken(request);
if (token == null) {
return Optional.empty();
}
try {
// JWT 파싱
Claims claims = Jwts.parserBuilder()
// HMAC SHA 키 객체 생성 (secret 길이와 안전성 체크)
.setSigningKey(Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8)))
.build()
.parseClaimsJws(token)
.getBody();
// 토큰에 empId 클레임이 있어야 함
Integer empId = claims.get("empId", Integer.class);
return Optional.ofNullable(empId);
} catch (Exception e) {
// 토큰 파싱/검증 실패 시 Optional.empty() 반환
return Optional.empty();
}
}
/**
* 현재 스레드의 HttpServletRequest 가져오기
* @return HttpServletRequest 또는 null
*/
private HttpServletRequest getCurrentHttpRequest() {
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attrs == null) return null;
return attrs.getRequest();
}
/**
* HttpServletRequest에서 Authorization 헤더의 Bearer 토큰 추출
* @param request 현재 HttpServletRequest
* @return JWT 문자열 또는 null
*/
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}