Fix : 수정
This commit is contained in:
parent
ef87bfbb0b
commit
0b78427304
@ -1,57 +1,59 @@
|
|||||||
package com.ktds.hi.member.config;
|
// package com.ktds.hi.member.config;
|
||||||
|
//
|
||||||
import com.ktds.hi.member.service.JwtTokenProvider;
|
//
|
||||||
import jakarta.servlet.FilterChain;
|
// import jakarta.servlet.FilterChain;
|
||||||
import jakarta.servlet.ServletException;
|
// import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
// import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
// import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.RequiredArgsConstructor;
|
// import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
// import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.core.Authentication;
|
// import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
// import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.util.StringUtils;
|
// import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
// import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
//
|
||||||
import java.io.IOException;
|
// import java.io.IOException;
|
||||||
|
//
|
||||||
/**
|
// import com.ktds.hi.common.security.JwtTokenProvider;
|
||||||
* JWT 인증 필터 클래스
|
//
|
||||||
* 요청 헤더의 JWT 토큰을 검증하고 인증 정보를 설정
|
// /**
|
||||||
*/
|
// * JWT 인증 필터 클래스
|
||||||
@RequiredArgsConstructor
|
// * 요청 헤더의 JWT 토큰을 검증하고 인증 정보를 설정
|
||||||
@Slf4j
|
// */
|
||||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
// @RequiredArgsConstructor
|
||||||
|
// @Slf4j
|
||||||
private final JwtTokenProvider tokenProvider;
|
// public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||||
|
//
|
||||||
@Override
|
// private final JwtTokenProvider tokenProvider;
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
//
|
||||||
FilterChain filterChain) throws ServletException, IOException {
|
// @Override
|
||||||
|
// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||||
try {
|
// FilterChain filterChain) throws ServletException, IOException {
|
||||||
String token = resolveToken(request);
|
//
|
||||||
|
// try {
|
||||||
if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
|
// String token = resolveToken(request);
|
||||||
Authentication authentication = tokenProvider.getAuthentication(token);
|
//
|
||||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
// if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
|
||||||
log.debug("JWT 토큰 인증 성공: {}", authentication.getName());
|
// Authentication authentication = tokenProvider.getAuthentication(token);
|
||||||
}
|
// SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
} catch (Exception e) {
|
// log.debug("JWT 토큰 인증 성공: {}", authentication.getName());
|
||||||
log.error("JWT 토큰 인증 실패", e);
|
// }
|
||||||
SecurityContextHolder.clearContext();
|
// } catch (Exception e) {
|
||||||
}
|
// log.error("JWT 토큰 인증 실패", e);
|
||||||
|
// SecurityContextHolder.clearContext();
|
||||||
filterChain.doFilter(request, response);
|
// }
|
||||||
}
|
//
|
||||||
|
// filterChain.doFilter(request, response);
|
||||||
/**
|
// }
|
||||||
* 요청 헤더에서 JWT 토큰 추출
|
//
|
||||||
*/
|
// /**
|
||||||
private String resolveToken(HttpServletRequest request) {
|
// * 요청 헤더에서 JWT 토큰 추출
|
||||||
String bearerToken = request.getHeader("Authorization");
|
// */
|
||||||
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
|
// private String resolveToken(HttpServletRequest request) {
|
||||||
return bearerToken.substring(7);
|
// String bearerToken = request.getHeader("Authorization");
|
||||||
}
|
// if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
|
||||||
return null;
|
// return bearerToken.substring(7);
|
||||||
}
|
// }
|
||||||
}
|
// return null;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@ -1,8 +1,9 @@
|
|||||||
package com.ktds.hi.member.config;
|
package com.ktds.hi.member.config;
|
||||||
|
|
||||||
|
|
||||||
import com.ktds.hi.member.config.JwtAuthenticationFilter;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.ktds.hi.member.service.JwtTokenProvider;
|
import com.ktds.hi.common.security.JwtTokenProvider;
|
||||||
|
import com.ktds.hi.common.security.JwtAuthenticationFilter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@ -26,7 +27,6 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class SecurityConfig {
|
public class SecurityConfig {
|
||||||
|
|
||||||
@Qualifier("memberJwtTokenProvider")
|
|
||||||
private final JwtTokenProvider jwtTokenProvider;
|
private final JwtTokenProvider jwtTokenProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,7 +54,7 @@ public class SecurityConfig {
|
|||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public JwtAuthenticationFilter jwtAuthenticationFilter() {
|
public JwtAuthenticationFilter jwtAuthenticationFilter() {
|
||||||
return new JwtAuthenticationFilter(jwtTokenProvider);
|
return new JwtAuthenticationFilter(jwtTokenProvider,new ObjectMapper());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.ktds.hi.member.service;
|
package com.ktds.hi.member.service;
|
||||||
|
|
||||||
|
import com.ktds.hi.common.security.JwtTokenProvider;
|
||||||
import com.ktds.hi.member.dto.*;
|
import com.ktds.hi.member.dto.*;
|
||||||
import com.ktds.hi.member.repository.entity.MemberEntity;
|
import com.ktds.hi.member.repository.entity.MemberEntity;
|
||||||
import com.ktds.hi.member.repository.jpa.MemberRepository;
|
import com.ktds.hi.member.repository.jpa.MemberRepository;
|
||||||
@ -11,6 +12,7 @@ import org.springframework.data.redis.core.RedisTemplate;
|
|||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,7 +26,6 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
|
|
||||||
private final MemberRepository memberRepository;
|
private final MemberRepository memberRepository;
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
@Qualifier("memberJwtTokenProvider")
|
|
||||||
private final JwtTokenProvider jwtTokenProvider;
|
private final JwtTokenProvider jwtTokenProvider;
|
||||||
private final SmsService smsService;
|
private final SmsService smsService;
|
||||||
private final RedisTemplate<String, String> redisTemplate;
|
private final RedisTemplate<String, String> redisTemplate;
|
||||||
@ -41,8 +42,12 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// JWT 토큰 생성
|
// JWT 토큰 생성
|
||||||
String accessToken = jwtTokenProvider.generateAccessToken(member.getId(), member.getRole());
|
String accessToken = jwtTokenProvider.createAccessToken(
|
||||||
String refreshToken = jwtTokenProvider.generateRefreshToken(member.getId());
|
member.getId().toString(),
|
||||||
|
Collections.singletonList(member.getRole())
|
||||||
|
);
|
||||||
|
String refreshToken = jwtTokenProvider.createRefreshToken(member.getId().toString());
|
||||||
|
|
||||||
|
|
||||||
// 리프레시 토큰 Redis 저장
|
// 리프레시 토큰 Redis 저장
|
||||||
redisTemplate.opsForValue().set(
|
redisTemplate.opsForValue().set(
|
||||||
@ -62,10 +67,12 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
@Override
|
@Override
|
||||||
public void logout(LogoutRequest request) {
|
public void logout(LogoutRequest request) {
|
||||||
// 리프레시 토큰에서 사용자 ID 추출
|
// 리프레시 토큰에서 사용자 ID 추출
|
||||||
Long memberId = jwtTokenProvider.getMemberIdFromToken(request.getRefreshToken());
|
String userId = jwtTokenProvider.getUserIdFromToken(request.getRefreshToken());
|
||||||
|
|
||||||
// Redis에서 리프레시 토큰 삭제
|
if (userId != null) {
|
||||||
redisTemplate.delete("refresh_token:" + memberId);
|
// Redis에서 리프레시 토큰 삭제
|
||||||
|
redisTemplate.delete("refresh_token:" + userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,7 +82,7 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
throw new BusinessException("유효하지 않은 리프레시 토큰입니다");
|
throw new BusinessException("유효하지 않은 리프레시 토큰입니다");
|
||||||
}
|
}
|
||||||
|
|
||||||
Long memberId = jwtTokenProvider.getMemberIdFromToken(refreshToken);
|
Long memberId = Long.parseLong(jwtTokenProvider.getUserIdFromToken(refreshToken));
|
||||||
|
|
||||||
// Redis에서 리프레시 토큰 확인
|
// Redis에서 리프레시 토큰 확인
|
||||||
String storedToken = redisTemplate.opsForValue().get("refresh_token:" + memberId);
|
String storedToken = redisTemplate.opsForValue().get("refresh_token:" + memberId);
|
||||||
@ -88,8 +95,12 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
.orElseThrow(() -> new BusinessException("존재하지 않는 사용자입니다"));
|
.orElseThrow(() -> new BusinessException("존재하지 않는 사용자입니다"));
|
||||||
|
|
||||||
// 새 토큰 생성
|
// 새 토큰 생성
|
||||||
String newAccessToken = jwtTokenProvider.generateAccessToken(member.getId(), member.getRole());
|
String newAccessToken = jwtTokenProvider.createAccessToken(
|
||||||
String newRefreshToken = jwtTokenProvider.generateRefreshToken(member.getId());
|
member.getId().toString(),
|
||||||
|
Collections.singletonList(member.getRole())
|
||||||
|
);
|
||||||
|
|
||||||
|
String newRefreshToken = jwtTokenProvider.createRefreshToken(member.getId().toString());
|
||||||
|
|
||||||
// 새 리프레시 토큰 Redis 저장
|
// 새 리프레시 토큰 Redis 저장
|
||||||
redisTemplate.opsForValue().set(
|
redisTemplate.opsForValue().set(
|
||||||
|
|||||||
@ -1,139 +0,0 @@
|
|||||||
package com.ktds.hi.member.service;
|
|
||||||
|
|
||||||
import io.jsonwebtoken.*;
|
|
||||||
import io.jsonwebtoken.security.Keys;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JWT 토큰 프로바이더 클래스
|
|
||||||
* JWT 토큰 생성, 검증, 파싱 기능을 제공
|
|
||||||
*/
|
|
||||||
@Component("memberJwtTokenProvider")
|
|
||||||
@Slf4j
|
|
||||||
public class JwtTokenProvider {
|
|
||||||
|
|
||||||
private final SecretKey secretKey;
|
|
||||||
private final long accessTokenExpiration;
|
|
||||||
private final long refreshTokenExpiration;
|
|
||||||
|
|
||||||
public JwtTokenProvider(@Value("${jwt.secret:mySecretKey123456789012345678901234567890}") String secret,
|
|
||||||
@Value("${jwt.access-token-expiration:1800000}") long accessTokenExpiration,
|
|
||||||
@Value("${jwt.refresh-token-expiration:604800000}") long refreshTokenExpiration) {
|
|
||||||
this.secretKey = Keys.hmacShaKeyFor(secret.getBytes());
|
|
||||||
this.accessTokenExpiration = accessTokenExpiration;
|
|
||||||
this.refreshTokenExpiration = refreshTokenExpiration;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 액세스 토큰 생성
|
|
||||||
*/
|
|
||||||
public String generateAccessToken(Long memberId, String role) {
|
|
||||||
Date now = new Date();
|
|
||||||
Date expiration = new Date(now.getTime() + accessTokenExpiration);
|
|
||||||
|
|
||||||
return Jwts.builder()
|
|
||||||
.setSubject(memberId.toString())
|
|
||||||
.claim("role", role)
|
|
||||||
.claim("type", "access")
|
|
||||||
.setIssuedAt(now)
|
|
||||||
.setExpiration(expiration)
|
|
||||||
.signWith(secretKey)
|
|
||||||
.compact();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 리프레시 토큰 생성
|
|
||||||
*/
|
|
||||||
public String generateRefreshToken(Long memberId) {
|
|
||||||
Date now = new Date();
|
|
||||||
Date expiration = new Date(now.getTime() + refreshTokenExpiration);
|
|
||||||
|
|
||||||
return Jwts.builder()
|
|
||||||
.setSubject(memberId.toString())
|
|
||||||
.claim("type", "refresh")
|
|
||||||
.setIssuedAt(now)
|
|
||||||
.setExpiration(expiration)
|
|
||||||
.signWith(secretKey)
|
|
||||||
.compact();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 토큰에서 인증 정보 추출
|
|
||||||
*/
|
|
||||||
public Authentication getAuthentication(String token) {
|
|
||||||
Claims claims = getClaims(token);
|
|
||||||
String memberId = claims.getSubject();
|
|
||||||
String role = (String) claims.get("role");
|
|
||||||
|
|
||||||
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + (role != null ? role : "USER"));
|
|
||||||
|
|
||||||
return new UsernamePasswordAuthenticationToken(
|
|
||||||
memberId,
|
|
||||||
null,
|
|
||||||
Collections.singletonList(authority)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 토큰 유효성 검증
|
|
||||||
*/
|
|
||||||
public boolean validateToken(String token) {
|
|
||||||
try {
|
|
||||||
getClaims(token);
|
|
||||||
return true;
|
|
||||||
} catch (ExpiredJwtException e) {
|
|
||||||
log.warn("JWT 토큰 만료: {}", e.getMessage());
|
|
||||||
} catch (UnsupportedJwtException e) {
|
|
||||||
log.warn("지원되지 않는 JWT 토큰: {}", e.getMessage());
|
|
||||||
} catch (MalformedJwtException e) {
|
|
||||||
log.warn("잘못된 형식의 JWT 토큰: {}", e.getMessage());
|
|
||||||
} catch (SecurityException | IllegalArgumentException e) {
|
|
||||||
log.warn("JWT 토큰 검증 실패: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 토큰에서 회원 ID 추출
|
|
||||||
*/
|
|
||||||
public Long getMemberIdFromToken(String token) {
|
|
||||||
Claims claims = getClaims(token);
|
|
||||||
return Long.parseLong(claims.getSubject());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 토큰에서 클레임 추출
|
|
||||||
*/
|
|
||||||
private Claims getClaims(String token) {
|
|
||||||
return Jwts.parser()
|
|
||||||
.setSigningKey(secretKey)
|
|
||||||
.build()
|
|
||||||
.parseClaimsJws(token)
|
|
||||||
.getBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 토큰 만료 시간 조회
|
|
||||||
*/
|
|
||||||
public Date getExpirationDateFromToken(String token) {
|
|
||||||
Claims claims = getClaims(token);
|
|
||||||
return claims.getExpiration();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 토큰이 만료되었는지 확인
|
|
||||||
*/
|
|
||||||
public boolean isTokenExpired(String token) {
|
|
||||||
Date expiration = getExpirationDateFromToken(token);
|
|
||||||
return expiration.before(new Date());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +1,11 @@
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':common')
|
implementation project(':common')
|
||||||
|
|
||||||
// File Storage
|
// AI and Location Services
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-webflux'
|
implementation 'org.springframework.boot:spring-boot-starter-webflux'
|
||||||
|
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.0'
|
||||||
|
|
||||||
|
|
||||||
|
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j:'
|
||||||
|
implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer:latest'
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user