From 71fc1903ed0590734bd28ad5251be8f636502f65 Mon Sep 17 00:00:00 2001 From: Dayeon-Hong Date: Tue, 6 Aug 2024 19:52:18 +0900 Subject: [PATCH 1/9] =?UTF-8?q?fix=20:=20skyscanner=20url=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=95=A8=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/flight/controller/FlightOfferController.java | 2 ++ .../isp/backend/domain/flight/mapper/FlightMapper.java | 2 +- .../domain/flight/service/FlightOfferServiceImpl.java | 8 +++----- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/isp/backend/domain/flight/controller/FlightOfferController.java b/backend/src/main/java/com/isp/backend/domain/flight/controller/FlightOfferController.java index 228fdabf..59e8a34a 100644 --- a/backend/src/main/java/com/isp/backend/domain/flight/controller/FlightOfferController.java +++ b/backend/src/main/java/com/isp/backend/domain/flight/controller/FlightOfferController.java @@ -63,6 +63,7 @@ public ResponseEntity addLikeFlight(@AuthenticationPrincipal CustomUserDet return ResponseEntity.status(HttpStatus.CREATED).body(flightId); } + /** 항공권 나의 좋아요 목록 불러오기 API **/ @GetMapping("/likes") public ResponseEntity> getLikedFlights(@AuthenticationPrincipal CustomUserDetails customUserDetails) { @@ -71,6 +72,7 @@ public ResponseEntity> getLikedFlights(@AuthenticationP return ResponseEntity.ok(likedFlights); } + /** 항공권 나의 좋아요 삭제 API **/ @DeleteMapping("/like/{id}") public ResponseEntity deleteLikeFlight(@AuthenticationPrincipal CustomUserDetails customUserDetails, diff --git a/backend/src/main/java/com/isp/backend/domain/flight/mapper/FlightMapper.java b/backend/src/main/java/com/isp/backend/domain/flight/mapper/FlightMapper.java index 7f92745f..38cf6b83 100644 --- a/backend/src/main/java/com/isp/backend/domain/flight/mapper/FlightMapper.java +++ b/backend/src/main/java/com/isp/backend/domain/flight/mapper/FlightMapper.java @@ -16,7 +16,7 @@ public class FlightMapper { public Flight toEntity(FlightLikeRequest request, Member member, Country departureIataCode, Country arrivalIataCode) { return Flight.builder() - .member(member) // 주입된 member 객체 사용 + .member(member) .carrierCode(request.getCarrierCode()) .price((double) request.getTotalPrice()) .abroadDuration(request.getAbroadDuration()) diff --git a/backend/src/main/java/com/isp/backend/domain/flight/service/FlightOfferServiceImpl.java b/backend/src/main/java/com/isp/backend/domain/flight/service/FlightOfferServiceImpl.java index 7dedf655..47336e3e 100644 --- a/backend/src/main/java/com/isp/backend/domain/flight/service/FlightOfferServiceImpl.java +++ b/backend/src/main/java/com/isp/backend/domain/flight/service/FlightOfferServiceImpl.java @@ -74,16 +74,15 @@ public String getFlightOffers(FlightSearchRequest request) throws ResponseExcept @Override public String generateSkyscannerUrl(SkyScannerRequest request) { // 요청 데이터 정제 - String departureDate = request.getDepartureDate().replace("-", "").substring(2); - String returnDate = (request.getReturnDate() != null) ? request.getReturnDate().replace("-", "").substring(2) : ""; + String departureDate = request.getDepartureDate().replace("-", "").substring(2) + "/"; + String returnDate = (request.getReturnDate() != null && !request.getReturnDate().isEmpty()) ? request.getReturnDate().replace("-", "").substring(2) + "/" : ""; int departureTimeMinutes = convertToMinutes(request.getDepartureTime()); String childrenParam = buildChildrenParam(request.getChildren()); String url = "https://www.skyscanner.co.kr/transport/flights/" + request.getDepartureIataCode().toLowerCase() + "/" + request.getArrivalIataCode().toLowerCase() + "/" + - departureDate + "/" + - returnDate + "/?adultsv2=" + request.getAdults() + childrenParam + + departureDate + returnDate + "?adultsv2=" + request.getAdults() + childrenParam + "&departure-times=" + departureTimeMinutes + "&inboundaltsenabled=false&outboundaltsenabled=false&ref=home&rtn=" + (returnDate.isEmpty() ? "0" : "1"); @@ -112,7 +111,6 @@ private String buildChildrenParam(int count) { /** * 항공권 좋아요 저장 - * **/ @Override @Transactional From a997b6349a28b27afc46c6554d6f7ec28aea2427 Mon Sep 17 00:00:00 2001 From: Dayeon-Hong Date: Tue, 6 Aug 2024 21:01:01 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat=20:=20=EC=8A=A4=EC=BC=80=EC=A4=84?= =?UTF-8?q?=EB=9F=AC=20=EC=82=AC=EC=9A=A9=ED=95=B4=20=ED=95=98=EB=A3=A8=20?= =?UTF-8?q?=ED=95=9C=EB=B2=88=20API=EC=8B=A4=ED=96=89=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/isp/backend/BackendApplication.java | 2 ++ .../service/ExchangeRateScheduler.java | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 backend/src/main/java/com/isp/backend/domain/country/service/ExchangeRateScheduler.java diff --git a/backend/src/main/java/com/isp/backend/BackendApplication.java b/backend/src/main/java/com/isp/backend/BackendApplication.java index b85f483f..5fd1a247 100644 --- a/backend/src/main/java/com/isp/backend/BackendApplication.java +++ b/backend/src/main/java/com/isp/backend/BackendApplication.java @@ -3,9 +3,11 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.client.RestTemplate; @SpringBootApplication +@EnableScheduling public class BackendApplication { public static void main(String[] args) { SpringApplication.run(BackendApplication.class, args); diff --git a/backend/src/main/java/com/isp/backend/domain/country/service/ExchangeRateScheduler.java b/backend/src/main/java/com/isp/backend/domain/country/service/ExchangeRateScheduler.java new file mode 100644 index 00000000..1e0201f7 --- /dev/null +++ b/backend/src/main/java/com/isp/backend/domain/country/service/ExchangeRateScheduler.java @@ -0,0 +1,22 @@ +package com.isp.backend.domain.country.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component +public class ExchangeRateScheduler { + + @Autowired + private ExchangeRateService exchangeRateService; + + @Scheduled(cron = "0 0 2 * * ?", zone = "Asia/Seoul") // 매일 한국시간 새벽 2시에 실행 + public void scheduleExchangeRateUpdate() { + try { + exchangeRateService.updateExchangeRates(); + } catch (Exception e) { + // 예외 처리 로직 + System.out.println("Failed to update exchange rates: " + e.getMessage()); + } + } +} \ No newline at end of file From 043b4964285f9856a5b2a6bdb7ee6b5704316034 Mon Sep 17 00:00:00 2001 From: Dayeon-Hong Date: Tue, 6 Aug 2024 23:29:30 +0900 Subject: [PATCH 3/9] =?UTF-8?q?fix=20:=20SpringSecurity=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EB=B6=80=EC=97=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/AccessTokenInvalidException.java | 10 ---------- .../member/MemberNotActivatedException.java | 13 ------------- .../exception/member/MemberNotFoundException.java | 13 ------------- .../member/RefreshTokenInvalidException.java | 12 ------------ .../backend/global/security/CustomUserDetails.java | 5 +++-- .../global/security/CustomUserDetailsService.java | 2 +- 6 files changed, 4 insertions(+), 51 deletions(-) delete mode 100644 backend/src/main/java/com/isp/backend/global/exception/member/AccessTokenInvalidException.java delete mode 100644 backend/src/main/java/com/isp/backend/global/exception/member/MemberNotActivatedException.java delete mode 100644 backend/src/main/java/com/isp/backend/global/exception/member/MemberNotFoundException.java delete mode 100644 backend/src/main/java/com/isp/backend/global/exception/member/RefreshTokenInvalidException.java diff --git a/backend/src/main/java/com/isp/backend/global/exception/member/AccessTokenInvalidException.java b/backend/src/main/java/com/isp/backend/global/exception/member/AccessTokenInvalidException.java deleted file mode 100644 index 51d25b1d..00000000 --- a/backend/src/main/java/com/isp/backend/global/exception/member/AccessTokenInvalidException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.isp.backend.global.exception.member; - -import com.isp.backend.global.exception.CustomException; -import com.isp.backend.global.exception.ErrorCode; - -public class AccessTokenInvalidException extends CustomException { - public AccessTokenInvalidException() { - super(ErrorCode.ACCESS_TOKEN_IS_INVALID); - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/isp/backend/global/exception/member/MemberNotActivatedException.java b/backend/src/main/java/com/isp/backend/global/exception/member/MemberNotActivatedException.java deleted file mode 100644 index 6d5f6490..00000000 --- a/backend/src/main/java/com/isp/backend/global/exception/member/MemberNotActivatedException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.isp.backend.global.exception.member; - -import com.isp.backend.global.exception.CustomException; -import com.isp.backend.global.exception.ErrorCode; - -public class MemberNotActivatedException extends CustomException { - - public MemberNotActivatedException() { - super(ErrorCode.MEMBER_NOT_ACTIVATED); - } - -} - diff --git a/backend/src/main/java/com/isp/backend/global/exception/member/MemberNotFoundException.java b/backend/src/main/java/com/isp/backend/global/exception/member/MemberNotFoundException.java deleted file mode 100644 index 7513c362..00000000 --- a/backend/src/main/java/com/isp/backend/global/exception/member/MemberNotFoundException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.isp.backend.global.exception.member; - -import com.isp.backend.global.exception.CustomException; -import com.isp.backend.global.exception.ErrorCode; - -public class MemberNotFoundException extends CustomException { - - public MemberNotFoundException() { - super(ErrorCode.MEMBER_NOT_FOUND); - } - -} - diff --git a/backend/src/main/java/com/isp/backend/global/exception/member/RefreshTokenInvalidException.java b/backend/src/main/java/com/isp/backend/global/exception/member/RefreshTokenInvalidException.java deleted file mode 100644 index 27e74565..00000000 --- a/backend/src/main/java/com/isp/backend/global/exception/member/RefreshTokenInvalidException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.isp.backend.global.exception.member; - -import com.isp.backend.global.exception.CustomException; -import com.isp.backend.global.exception.ErrorCode; - -public class RefreshTokenInvalidException extends CustomException { - - public RefreshTokenInvalidException() { - super(ErrorCode.REFRESH_TOKEN_IS_INVALID); - } - -} diff --git a/backend/src/main/java/com/isp/backend/global/security/CustomUserDetails.java b/backend/src/main/java/com/isp/backend/global/security/CustomUserDetails.java index 4701cb8e..7eda83dc 100644 --- a/backend/src/main/java/com/isp/backend/global/security/CustomUserDetails.java +++ b/backend/src/main/java/com/isp/backend/global/security/CustomUserDetails.java @@ -3,6 +3,7 @@ import com.isp.backend.domain.member.entity.Member; import lombok.RequiredArgsConstructor; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; @@ -24,7 +25,7 @@ public String getUsername() { //유저 이메일 가져오기 @Override public String getPassword() { - return member.getUid(); + return null; // 패스워드가 없으므로 null 반환 } @Override @@ -49,7 +50,7 @@ public boolean isEnabled() { @Override public Collection getAuthorities() { - return Collections.emptyList(); + return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); } } diff --git a/backend/src/main/java/com/isp/backend/global/security/CustomUserDetailsService.java b/backend/src/main/java/com/isp/backend/global/security/CustomUserDetailsService.java index 161fc6fa..2dff7f95 100644 --- a/backend/src/main/java/com/isp/backend/global/security/CustomUserDetailsService.java +++ b/backend/src/main/java/com/isp/backend/global/security/CustomUserDetailsService.java @@ -2,7 +2,7 @@ import com.isp.backend.domain.member.entity.Member; import com.isp.backend.domain.member.repository.MemberRepository; -import com.isp.backend.global.exception.member.MemberNotFoundException; +import com.isp.backend.global.exception.common.MemberNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; From dda3b0cb820b8e429609b48d29977b5605db3b48 Mon Sep 17 00:00:00 2001 From: Dayeon-Hong Date: Tue, 6 Aug 2024 23:30:51 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat=20:=20token=EC=83=9D=EC=84=B1=EC=8B=9C?= =?UTF-8?q?=20=EA=B6=8C=ED=95=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../isp/backend/global/jwt/TokenProvider.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/isp/backend/global/jwt/TokenProvider.java b/backend/src/main/java/com/isp/backend/global/jwt/TokenProvider.java index 7952955f..08762c69 100644 --- a/backend/src/main/java/com/isp/backend/global/jwt/TokenProvider.java +++ b/backend/src/main/java/com/isp/backend/global/jwt/TokenProvider.java @@ -9,10 +9,14 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import java.security.Key; +import java.util.Collection; +import java.util.Collections; import java.util.Date; @Slf4j @@ -21,8 +25,6 @@ public class TokenProvider implements InitializingBean { private final CustomUserDetailsService customUserDetailsService; -// private final RefreshTokenRepository refreshTokenRepository; - private final String secret; private final Long accessExpirationTime; private final Long refreshExpirationTime; @@ -83,15 +85,17 @@ public String createRefreshToken(String uid) { return refreshToken; } - // 토큰에서 정보 추출 - public Authentication getAuthentication(String token) { + public Authentication getAuthentication(String token) { String uid = parseClaims(token).getSubject(); UserDetails userDetails = customUserDetailsService.loadUserByUsername(uid); - return new UsernamePasswordAuthenticationToken(userDetails, token); + Collection authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); + + return new UsernamePasswordAuthenticationToken(userDetails, token, authorities); } + // Access Token 검증 public boolean validateAccessToken(String accessToken) { try { @@ -144,7 +148,7 @@ public boolean validateRefreshToken(String refreshToken) { return false; } - + // 토큰에서 uid 가져오기 public String getUid(String token) { return parseClaims(token).getSubject(); } @@ -158,6 +162,7 @@ private Claims parseClaims(String token) { .getBody(); } + // 토큰 만료 시간 가져오기 private Date getExpirationTime(Long expirationTime) { return new Date((new Date()).getTime() + expirationTime); } From 8afcd250746f492753339de1d66708e4aee210dc Mon Sep 17 00:00:00 2001 From: Dayeon-Hong Date: Tue, 6 Aug 2024 23:31:56 +0900 Subject: [PATCH 5/9] =?UTF-8?q?fix=20:=20=ED=86=A0=ED=81=B0=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 한글로 수정 및 사용하지 않는 공백 삭제 --- .../com/isp/backend/global/jwt/JwtAccessDeniedHandler.java | 2 -- .../isp/backend/global/jwt/JwtAuthenticationEntryPoint.java | 2 +- .../com/isp/backend/global/jwt/JwtAuthenticationFilter.java | 4 ++++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/isp/backend/global/jwt/JwtAccessDeniedHandler.java b/backend/src/main/java/com/isp/backend/global/jwt/JwtAccessDeniedHandler.java index a9bb9a01..d561f67e 100644 --- a/backend/src/main/java/com/isp/backend/global/jwt/JwtAccessDeniedHandler.java +++ b/backend/src/main/java/com/isp/backend/global/jwt/JwtAccessDeniedHandler.java @@ -18,7 +18,5 @@ public void handle(HttpServletRequest request, HttpServletResponse response, Acc // 인가되지 않은(권한이 없는) 요청이 들어왔을 때의 처리를 담당 - `handle` 메서드는 예외 처리 및 로깅을 수행한다. log.error("Forbidden Request : {}", request.getRequestURI()); response.sendError(HttpServletResponse.SC_FORBIDDEN); - } - } diff --git a/backend/src/main/java/com/isp/backend/global/jwt/JwtAuthenticationEntryPoint.java b/backend/src/main/java/com/isp/backend/global/jwt/JwtAuthenticationEntryPoint.java index 1f69d515..1ca1530a 100644 --- a/backend/src/main/java/com/isp/backend/global/jwt/JwtAuthenticationEntryPoint.java +++ b/backend/src/main/java/com/isp/backend/global/jwt/JwtAuthenticationEntryPoint.java @@ -16,7 +16,7 @@ public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { // 인증되지 않은 요청이 들어왔을 때의 처리를 담당 - `commence` 메서드는 예외 처리 및 로깅을 수행한다. - log.error("Unauthorized Request : {}", request.getRequestURI()); + log.error("인증되지 않은 요청입니다. : {}", request.getRequestURI()); response.sendError(HttpServletResponse.SC_UNAUTHORIZED); } } diff --git a/backend/src/main/java/com/isp/backend/global/jwt/JwtAuthenticationFilter.java b/backend/src/main/java/com/isp/backend/global/jwt/JwtAuthenticationFilter.java index 20190d03..2061acb4 100644 --- a/backend/src/main/java/com/isp/backend/global/jwt/JwtAuthenticationFilter.java +++ b/backend/src/main/java/com/isp/backend/global/jwt/JwtAuthenticationFilter.java @@ -5,6 +5,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; @@ -13,6 +14,7 @@ import java.io.IOException; +@Slf4j @Component @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { @@ -33,6 +35,8 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse if (token != null && tokenProvider.validateAccessToken(token)) { Authentication authentication = tokenProvider.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(authentication); + } else { + log.warn("Invalid or missing token"); } filterChain.doFilter(request, response); From 8a6190efae0453273890a118e37f01e1706be2b5 Mon Sep 17 00:00:00 2001 From: Dayeon-Hong Date: Tue, 6 Aug 2024 23:32:40 +0900 Subject: [PATCH 6/9] =?UTF-8?q?fix=20:=20WebSecurityConfig=EC=97=90=20whit?= =?UTF-8?q?eList=20=EC=A0=81=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/security/WebSecurityConfig.java | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/backend/src/main/java/com/isp/backend/global/security/WebSecurityConfig.java b/backend/src/main/java/com/isp/backend/global/security/WebSecurityConfig.java index f1b9815c..f6b09760 100644 --- a/backend/src/main/java/com/isp/backend/global/security/WebSecurityConfig.java +++ b/backend/src/main/java/com/isp/backend/global/security/WebSecurityConfig.java @@ -18,15 +18,14 @@ import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - @RequiredArgsConstructor @Configuration -@EnableWebSecurity // Spring Security 활성화 +@EnableWebSecurity public class WebSecurityConfig { private static final String[] AUTH_WHITE_LIST = { "/members/login", - "/api/members/login", + "/members/refresh", "/members/test", "/error", "/h2-console/**" @@ -42,28 +41,21 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti http .cors(corsConfigurer -> corsConfigurer.configurationSource(corsConfigurationSource())) // cors 구성 .csrf(CsrfConfigurer::disable) // csrf 보호 비활성화 - .formLogin(AbstractHttpConfigurer::disable) // 폼 기반 login 비활성화 - .httpBasic(HttpBasicConfigurer::disable) // HTTP basic 인증 비활성화 + .formLogin(AbstractHttpConfigurer::disable) // 폼 기반 login 비활성화 + .httpBasic(HttpBasicConfigurer::disable) // HTTP basic 인증 비활성화 .sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 세션 생성 X -// .authorizeHttpRequests( -// requests -> { -// for (String url : AUTH_WHITE_LIST) { -// requests.requestMatchers(url).permitAll(); // 인증 없이 들어가는 url -// } -// requests.anyRequest().authenticated(); -// } -// ) .authorizeHttpRequests(authorizeRequests -> authorizeRequests - .requestMatchers("/**").permitAll() // 모든 요청에 대해 모든 사용자에게 권한 부여 + .requestMatchers(AUTH_WHITE_LIST).permitAll() // AUTH_WHITE_LIST에 포함된 URL은 인증 없이 접근 가능 + .anyRequest().authenticated() // 나머지 모든 요청은 인증 필요 ) - .exceptionHandling(exceptionHandlingConfigurer -> exceptionHandlingConfigurer // 예외처리 구성 - 인증 진입 점 + 엑세스 거부 헨들러 지정 + .exceptionHandling(exceptionHandlingConfigurer -> exceptionHandlingConfigurer // 예외처리 구성 - 인증 진입 점 + 엑세스 거부 헨들러 지정 .authenticationEntryPoint(jwtAuthenticationEntryPoint) .accessDeniedHandler(jwtAccessDeniedHandler)); - http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); // JWT 기반 인증 처리 + http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); // JWT 기반 인증 처리 return http.build(); } From 6bc5a91ea2705b2451b770b86328d2aeb84d41d3 Mon Sep 17 00:00:00 2001 From: Dayeon-Hong Date: Tue, 6 Aug 2024 23:35:33 +0900 Subject: [PATCH 7/9] =?UTF-8?q?fix=20:=20=ED=86=A0=ED=81=B0=20=EC=9E=AC?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/controller/MemberController.java | 1 - .../domain/member/service/MemberServiceImpl.java | 8 ++++---- .../common/RefreshTokenInvalidException.java | 12 ++++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 backend/src/main/java/com/isp/backend/global/exception/common/RefreshTokenInvalidException.java diff --git a/backend/src/main/java/com/isp/backend/domain/member/controller/MemberController.java b/backend/src/main/java/com/isp/backend/domain/member/controller/MemberController.java index bba1ef18..1dfe8c9d 100644 --- a/backend/src/main/java/com/isp/backend/domain/member/controller/MemberController.java +++ b/backend/src/main/java/com/isp/backend/domain/member/controller/MemberController.java @@ -48,7 +48,6 @@ public ResponseEntity authRecreate(@RequestBody AuthRecreateRequest auth /** 멤버 정보 조회 **/ @GetMapping("/information") public ResponseEntity getMemberInfo(@AuthenticationPrincipal CustomUserDetails customUserDetails) { - return ResponseEntity.ok(memberService.getMemberInfo(customUserDetails.getUsername())); } diff --git a/backend/src/main/java/com/isp/backend/domain/member/service/MemberServiceImpl.java b/backend/src/main/java/com/isp/backend/domain/member/service/MemberServiceImpl.java index 0d002cf6..bc385072 100644 --- a/backend/src/main/java/com/isp/backend/domain/member/service/MemberServiceImpl.java +++ b/backend/src/main/java/com/isp/backend/domain/member/service/MemberServiceImpl.java @@ -6,9 +6,9 @@ import com.isp.backend.domain.member.dto.request.SignUpRequest; import com.isp.backend.domain.member.entity.Member; import com.isp.backend.domain.member.repository.MemberRepository; -import com.isp.backend.global.exception.member.AuthenticationFailedException; -import com.isp.backend.global.exception.member.MemberNotActivatedException; -import com.isp.backend.global.exception.member.MemberNotFoundException; +import com.isp.backend.global.exception.common.MemberNotActivatedException; +import com.isp.backend.global.exception.common.MemberNotFoundException; +import com.isp.backend.global.exception.common.RefreshTokenInvalidException; import com.isp.backend.global.jwt.TokenProvider; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -99,7 +99,7 @@ public void signUp(SignUpRequest signUpRequest, String memberUid) { public ResponseEntity authRecreate(AuthRecreateRequest authRecreateRequest) { if (!tokenProvider.validateRefreshToken(authRecreateRequest.getRefreshToken())) { - throw new AuthenticationFailedException(); + throw new RefreshTokenInvalidException(); } String uid = tokenProvider.getUid(authRecreateRequest.getRefreshToken()); diff --git a/backend/src/main/java/com/isp/backend/global/exception/common/RefreshTokenInvalidException.java b/backend/src/main/java/com/isp/backend/global/exception/common/RefreshTokenInvalidException.java new file mode 100644 index 00000000..e8183a8e --- /dev/null +++ b/backend/src/main/java/com/isp/backend/global/exception/common/RefreshTokenInvalidException.java @@ -0,0 +1,12 @@ +package com.isp.backend.global.exception.common; + +import com.isp.backend.global.exception.CustomException; +import com.isp.backend.global.exception.ErrorCode; + +public class RefreshTokenInvalidException extends CustomException { + + public RefreshTokenInvalidException() { + super(ErrorCode.REFRESH_TOKEN_IS_INVALID); + } + +} From dd9d4dca2cd41650ee423c75d0464e38cb07e93e Mon Sep 17 00:00:00 2001 From: Dayeon-Hong Date: Tue, 6 Aug 2024 23:36:17 +0900 Subject: [PATCH 8/9] =?UTF-8?q?fix=20:=20=EC=97=90=EB=9F=AC=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../schedule/service/ScheduleServiceImpl.java | 2 +- .../com/isp/backend/global/exception/ErrorCode.java | 4 ++-- .../common/AccessTokenInvalidException.java | 10 ++++++++++ .../common/AuthenticationFailedException.java | 10 ++++++++++ .../common/MemberNotActivatedException.java | 13 +++++++++++++ .../exception/common/MemberNotFoundException.java | 13 +++++++++++++ .../member/AuthenticationFailedException.java | 11 ----------- 7 files changed, 49 insertions(+), 14 deletions(-) create mode 100644 backend/src/main/java/com/isp/backend/global/exception/common/AccessTokenInvalidException.java create mode 100644 backend/src/main/java/com/isp/backend/global/exception/common/AuthenticationFailedException.java create mode 100644 backend/src/main/java/com/isp/backend/global/exception/common/MemberNotActivatedException.java create mode 100644 backend/src/main/java/com/isp/backend/global/exception/common/MemberNotFoundException.java delete mode 100644 backend/src/main/java/com/isp/backend/global/exception/member/AuthenticationFailedException.java diff --git a/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleServiceImpl.java b/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleServiceImpl.java index 91d72578..db840007 100644 --- a/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleServiceImpl.java +++ b/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleServiceImpl.java @@ -13,7 +13,7 @@ import com.isp.backend.domain.schedule.repository.ScheduleRepository; import com.isp.backend.domain.scheduleDetail.entity.ScheduleDetail; import com.isp.backend.domain.scheduleDetail.repository.ScheduleDetailRepository; -import com.isp.backend.global.exception.member.MemberNotFoundException; +import com.isp.backend.global.exception.common.MemberNotFoundException; import com.isp.backend.global.exception.schedule.CountryNotFoundException; import com.isp.backend.global.exception.schedule.NotYourScheduleException; import com.isp.backend.global.exception.schedule.ScheduleNotFoundException; diff --git a/backend/src/main/java/com/isp/backend/global/exception/ErrorCode.java b/backend/src/main/java/com/isp/backend/global/exception/ErrorCode.java index 5d7e1037..36e726af 100644 --- a/backend/src/main/java/com/isp/backend/global/exception/ErrorCode.java +++ b/backend/src/main/java/com/isp/backend/global/exception/ErrorCode.java @@ -11,8 +11,8 @@ public enum ErrorCode { // Common MEMBER_NOT_FOUND(HttpStatus.UNAUTHORIZED, "U001", "사용자를 찾을 수 없습니다."), - SOCIAL_AUTHENTICATION_FAILED(HttpStatus.UNAUTHORIZED, "U002", "사용자가 OAuth2 로그인에 실패하였습니다."), - MEMBER_NOT_ACTIVATED(HttpStatus.BAD_REQUEST, "U003", "사용자가 활성화 상태가 아닙니다."), + MEMBER_NOT_ACTIVATED(HttpStatus.BAD_REQUEST, "U002", "사용자가 활성화 상태가 아닙니다."), + AUTHENTICATION_FAILED(HttpStatus.FORBIDDEN, "U003", "권한이 없는 요청입니다. 토큰을 추가해주세요."), ACCESS_TOKEN_IS_INVALID(HttpStatus.UNAUTHORIZED, "U004", "엑세스 토큰이 유효하지 않습니다."), REFRESH_TOKEN_IS_INVALID(HttpStatus.UNAUTHORIZED, "U005", "리프레시 토큰이 유효하지 않습니다."), diff --git a/backend/src/main/java/com/isp/backend/global/exception/common/AccessTokenInvalidException.java b/backend/src/main/java/com/isp/backend/global/exception/common/AccessTokenInvalidException.java new file mode 100644 index 00000000..f7e20f40 --- /dev/null +++ b/backend/src/main/java/com/isp/backend/global/exception/common/AccessTokenInvalidException.java @@ -0,0 +1,10 @@ +package com.isp.backend.global.exception.common; + +import com.isp.backend.global.exception.CustomException; +import com.isp.backend.global.exception.ErrorCode; + +public class AccessTokenInvalidException extends CustomException { + public AccessTokenInvalidException() { + super(ErrorCode.ACCESS_TOKEN_IS_INVALID); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/isp/backend/global/exception/common/AuthenticationFailedException.java b/backend/src/main/java/com/isp/backend/global/exception/common/AuthenticationFailedException.java new file mode 100644 index 00000000..1e447b01 --- /dev/null +++ b/backend/src/main/java/com/isp/backend/global/exception/common/AuthenticationFailedException.java @@ -0,0 +1,10 @@ +package com.isp.backend.global.exception.common; + +import com.isp.backend.global.exception.CustomException; +import com.isp.backend.global.exception.ErrorCode; + +public class AuthenticationFailedException extends CustomException { + + public AuthenticationFailedException() {super(ErrorCode.AUTHENTICATION_FAILED);} + +} diff --git a/backend/src/main/java/com/isp/backend/global/exception/common/MemberNotActivatedException.java b/backend/src/main/java/com/isp/backend/global/exception/common/MemberNotActivatedException.java new file mode 100644 index 00000000..d97d6f73 --- /dev/null +++ b/backend/src/main/java/com/isp/backend/global/exception/common/MemberNotActivatedException.java @@ -0,0 +1,13 @@ +package com.isp.backend.global.exception.common; + +import com.isp.backend.global.exception.CustomException; +import com.isp.backend.global.exception.ErrorCode; + +public class MemberNotActivatedException extends CustomException { + + public MemberNotActivatedException() { + super(ErrorCode.MEMBER_NOT_ACTIVATED); + } + +} + diff --git a/backend/src/main/java/com/isp/backend/global/exception/common/MemberNotFoundException.java b/backend/src/main/java/com/isp/backend/global/exception/common/MemberNotFoundException.java new file mode 100644 index 00000000..ca40fb63 --- /dev/null +++ b/backend/src/main/java/com/isp/backend/global/exception/common/MemberNotFoundException.java @@ -0,0 +1,13 @@ +package com.isp.backend.global.exception.common; + +import com.isp.backend.global.exception.CustomException; +import com.isp.backend.global.exception.ErrorCode; + +public class MemberNotFoundException extends CustomException { + + public MemberNotFoundException() { + super(ErrorCode.MEMBER_NOT_FOUND); + } + +} + diff --git a/backend/src/main/java/com/isp/backend/global/exception/member/AuthenticationFailedException.java b/backend/src/main/java/com/isp/backend/global/exception/member/AuthenticationFailedException.java deleted file mode 100644 index 8b44c5a5..00000000 --- a/backend/src/main/java/com/isp/backend/global/exception/member/AuthenticationFailedException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.isp.backend.global.exception.member; - -import com.isp.backend.global.exception.CustomException; -import com.isp.backend.global.exception.ErrorCode; - -public class AuthenticationFailedException extends CustomException { - - public AuthenticationFailedException() { - super(ErrorCode.SOCIAL_AUTHENTICATION_FAILED); - } -} From 505ccc6279a3b1915ffd23969311c0e491f5485e Mon Sep 17 00:00:00 2001 From: Dayeon-Hong Date: Tue, 6 Aug 2024 23:43:49 +0900 Subject: [PATCH 9/9] =?UTF-8?q?fix=20:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=96=B4=EB=85=B8=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=82=AD=EC=A0=9C=20@AuthenticationPrinci?= =?UTF-8?q?pal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../country/controller/CountryController.java | 14 +++++--------- .../flight/controller/FlightOfferController.java | 8 ++------ 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/backend/src/main/java/com/isp/backend/domain/country/controller/CountryController.java b/backend/src/main/java/com/isp/backend/domain/country/controller/CountryController.java index dbd4fe3a..ab75715f 100644 --- a/backend/src/main/java/com/isp/backend/domain/country/controller/CountryController.java +++ b/backend/src/main/java/com/isp/backend/domain/country/controller/CountryController.java @@ -5,19 +5,14 @@ import com.isp.backend.domain.country.dto.response.ExchangeRateResponse; import com.isp.backend.domain.country.dto.response.LocationResponse; import com.isp.backend.domain.country.dto.response.WeatherResponse; -import com.isp.backend.domain.country.entity.ExchangeRate; import com.isp.backend.domain.country.service.CountryService; import com.isp.backend.domain.country.service.ExchangeRateService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.io.IOException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.time.LocalTime; import java.util.List; -import java.util.Map; import java.util.Optional; @RestController @@ -41,7 +36,7 @@ public ResponseEntity findLocation(@RequestBody LocationReques } - /** 현재 날씨 정보 가져오기 **/ + /** 여행지 현재 날씨 정보 가져오기 **/ @PostMapping("/weather/current") public ResponseEntity getCurrentWeather(@RequestBody LocationRequest requestDTO) { String city = requestDTO.getCountry(); @@ -50,7 +45,7 @@ public ResponseEntity getCurrentWeather(@RequestBody LocationRe } - /** 한 주 날씨 정보 조회 **/ + /** 여행지 한 주 날씨 정보 조회 **/ @PostMapping("/weather/weekly") public ResponseEntity> getWeeklyWeather(@RequestBody LocationRequest requestDTO) { String city = requestDTO.getCountry(); @@ -60,7 +55,7 @@ public ResponseEntity> getWeeklyWeather(@RequestBody } - /** 환율 정보 업데이트 API **/ + /** 여행지 환율 정보 업데이트 API **/ @GetMapping("/exchange-rates/update") public String updateExchangeRate() { try { @@ -71,7 +66,8 @@ public String updateExchangeRate() { } } - /** 환율 정보 조회 API **/ + + /** 여행지 환율 정보 조회 API **/ @GetMapping("/exchange-rates") public ResponseEntity> getAllExchangeRates() { List exchangeRates = exchangeRateService.getAllExchangeRates(); diff --git a/backend/src/main/java/com/isp/backend/domain/flight/controller/FlightOfferController.java b/backend/src/main/java/com/isp/backend/domain/flight/controller/FlightOfferController.java index 59e8a34a..684adfe6 100644 --- a/backend/src/main/java/com/isp/backend/domain/flight/controller/FlightOfferController.java +++ b/backend/src/main/java/com/isp/backend/domain/flight/controller/FlightOfferController.java @@ -28,9 +28,7 @@ public class FlightOfferController { /** 항공권 검색 API **/ @PostMapping("/search") - public ResponseEntity getFlightOffers(@AuthenticationPrincipal CustomUserDetails customUserDetails, - @RequestBody FlightSearchRequest request) { - String memberUid = customUserDetails.getUsername(); + public ResponseEntity getFlightOffers(@RequestBody FlightSearchRequest request) { try { String flightOffersJson = flightOfferService.getFlightOffers(request); return ResponseEntity.ok(flightOffersJson); @@ -42,9 +40,7 @@ public ResponseEntity getFlightOffers(@AuthenticationPrincipal CustomUse /** 항공권 선택시 스카이스캐너 사이트로 연결 API **/ @PostMapping("/connect") - public ResponseEntity getFlightSearchUrl(@AuthenticationPrincipal CustomUserDetails customUserDetails, - @RequestBody SkyScannerRequest request) { - String memberUid = customUserDetails.getUsername(); + public ResponseEntity getFlightSearchUrl(@RequestBody SkyScannerRequest request) { try { String skyscannerUrl = flightOfferService.generateSkyscannerUrl(request); return ResponseEntity.ok("{\"skyscannerUrl\": \"" + skyscannerUrl + "\"}");