[JWT 개선] MemberDto의 권한 반환 방식을 수정하고, JwtTokenIssuanceFilter 및 JwtTokenValidationFilter에서 Access Token 생성 로직을 개선하여 사용자 정보를 포함하도록 변경. JwtUtils에 사용자 세부정보 생성을 위한 메서드 추가.

This commit is contained in:
2025-09-01 14:17:06 +09:00
parent ed4d386d53
commit 063bd7cc74
4 changed files with 46 additions and 8 deletions

View File

@@ -32,7 +32,7 @@ public class MemberDto implements UserDetails {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
return Collections.emptyList();
}
@Override

View File

@@ -66,7 +66,7 @@ public class JwtTokenIssuanceFilter extends UsernamePasswordAuthenticationFilter
MemberDto member = (MemberDto) userDetails;
// 토큰 생성
String accessToken = jwtUtils.createAccessToken(member.getUserId());
String accessToken = jwtUtils.createAccessToken(member.getOid(), member.getUserId(), member.getName());
String refreshToken = jwtUtils.createRefreshToken(member.getUserId(), httpUtils.getClientIp());
member.setRefreshToken(refreshToken);

View File

@@ -52,13 +52,13 @@ public class JwtTokenValidationFilter extends OncePerRequestFilter {
log.debug("JWT 토큰 검증 필터 실행 - URI: {}", request.getRequestURI());
String accessToken = jwtUtils.extractAccessJwtFromRequest(request);
String accessToken = jwtUtils.extractAccessJwtFromCookie(request);
String refreshToken = jwtUtils.extractRefreshJwtFromCookie(request);
// Access Token이 있고 유효한 경우
if (accessToken != null && jwtUtils.validateAccessToken(accessToken)) {
String username = jwtUtils.extractUsername(accessToken);
UserDetails userDetails = memberService.loadUserByUsername(username);
UserDetails userDetails = jwtUtils.createUserDetailsFromToken(accessToken);
if (userDetails != null) {
UsernamePasswordAuthenticationToken authentication =
@@ -94,7 +94,11 @@ public class JwtTokenValidationFilter extends OncePerRequestFilter {
UserDetails userDetails = memberService.loadUserByUsername(username);
// 새로운 Access Token 생성
String newAccessToken = jwtUtils.createAccessToken(username);
String newAccessToken = jwtUtils.createAccessToken(
((MemberDto) userDetails).getOid(),
userDetails.getUsername(),
((MemberDto) userDetails).getName()
);
// 새로운 Access Token을 쿠키에 설정
jwtUtils.setAccessTokenCookie(response, newAccessToken);

View File

@@ -8,10 +8,12 @@ import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import com.bio.bio_backend.domain.base.member.service.MemberService;
import com.bio.bio_backend.domain.base.member.dto.MemberDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
@@ -44,6 +46,18 @@ public class JwtUtils {
.compact();
}
// Token 생성 (사용자 정보 포함)
public String generateToken(Long oid, String username, String name, long expirationTime) {
return Jwts.builder()
.subject(username)
.claim("oid", oid)
.claim("name", name)
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + expirationTime))
.signWith(getSigningKey())
.compact();
}
// Token 생성(IP 정보 포함)
public String generateToken(String username, String clientIp, long expirationTime) {
return Jwts.builder()
@@ -56,11 +70,12 @@ public class JwtUtils {
}
// Access Token 생성
public String createAccessToken(String username) {
public String createAccessToken(Long oid, String username, String name) {
long expirationTime = Long.parseLong(Objects.requireNonNull(env.getProperty("token.expiration_time_access")));
return generateToken(username, expirationTime);
return generateToken(oid, username, name, expirationTime);
}
// Refresh Token 생성 시 IP 정보 포함
public String createRefreshToken(String username, String clientIp) {
long expirationTime = Long.parseLong(Objects.requireNonNull(env.getProperty("token.expiration_time_refresh")));
@@ -131,7 +146,7 @@ public class JwtUtils {
}
// Access Token을 쿠키에서 추출
public String extractAccessJwtFromRequest(HttpServletRequest request) {
public String extractAccessJwtFromCookie(HttpServletRequest request) {
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if ("AccessToken".equals(cookie.getName())) {
@@ -191,4 +206,23 @@ public class JwtUtils {
cookie.setMaxAge(maxAge);
response.addCookie(cookie);
}
public UserDetails createUserDetailsFromToken(String accessToken) {
try {
Claims claims = extractAllClaims(accessToken);
String username = claims.getSubject();
Long oid = claims.get("oid", Long.class);
String name = claims.get("name", String.class);
// 토큰에서 직접 UserDetails 생성 (DB 조회 없음)
return MemberDto.builder()
.oid(oid)
.userId(username)
.name(name)
.build();
} catch (Exception e) {
log.debug("토큰에서 UserDetails 생성 실패: {}", e.getMessage());
return null;
}
}
}