Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backend : Fix] 항공권 url, 스프링 시큐리티 수정 #116

Merged
merged 9 commits into from
Aug 6, 2024
2 changes: 2 additions & 0 deletions backend/src/main/java/com/isp/backend/BackendApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -41,7 +36,7 @@ public ResponseEntity<LocationResponse> findLocation(@RequestBody LocationReques
}


/** 현재 날씨 정보 가져오기 **/
/** 여행지 현재 날씨 정보 가져오기 **/
@PostMapping("/weather/current")
public ResponseEntity<WeatherResponse> getCurrentWeather(@RequestBody LocationRequest requestDTO) {
String city = requestDTO.getCountry();
Expand All @@ -50,7 +45,7 @@ public ResponseEntity<WeatherResponse> getCurrentWeather(@RequestBody LocationRe
}


/** 한 주 날씨 정보 조회 **/
/** 여행지 한 주 날씨 정보 조회 **/
@PostMapping("/weather/weekly")
public ResponseEntity<List<DailyWeatherResponse>> getWeeklyWeather(@RequestBody LocationRequest requestDTO) {
String city = requestDTO.getCountry();
Expand All @@ -60,7 +55,7 @@ public ResponseEntity<List<DailyWeatherResponse>> getWeeklyWeather(@RequestBody
}


/** 환율 정보 업데이트 API **/
/** 여행지 환율 정보 업데이트 API **/
@GetMapping("/exchange-rates/update")
public String updateExchangeRate() {
try {
Expand All @@ -71,7 +66,8 @@ public String updateExchangeRate() {
}
}

/** 환율 정보 조회 API **/

/** 여행지 환율 정보 조회 API **/
@GetMapping("/exchange-rates")
public ResponseEntity<List<ExchangeRateResponse>> getAllExchangeRates() {
List<ExchangeRateResponse> exchangeRates = exchangeRateService.getAllExchangeRates();
Expand Down
Original file line number Diff line number Diff line change
@@ -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());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ public class FlightOfferController {

/** 항공권 검색 API **/
@PostMapping("/search")
public ResponseEntity<String> getFlightOffers(@AuthenticationPrincipal CustomUserDetails customUserDetails,
@RequestBody FlightSearchRequest request) {
String memberUid = customUserDetails.getUsername();
public ResponseEntity<String> getFlightOffers(@RequestBody FlightSearchRequest request) {
try {
String flightOffersJson = flightOfferService.getFlightOffers(request);
return ResponseEntity.ok(flightOffersJson);
Expand All @@ -42,9 +40,7 @@ public ResponseEntity<String> getFlightOffers(@AuthenticationPrincipal CustomUse

/** 항공권 선택시 스카이스캐너 사이트로 연결 API **/
@PostMapping("/connect")
public ResponseEntity<String> getFlightSearchUrl(@AuthenticationPrincipal CustomUserDetails customUserDetails,
@RequestBody SkyScannerRequest request) {
String memberUid = customUserDetails.getUsername();
public ResponseEntity<String> getFlightSearchUrl(@RequestBody SkyScannerRequest request) {
try {
String skyscannerUrl = flightOfferService.generateSkyscannerUrl(request);
return ResponseEntity.ok("{\"skyscannerUrl\": \"" + skyscannerUrl + "\"}");
Expand All @@ -63,6 +59,7 @@ public ResponseEntity<Long> addLikeFlight(@AuthenticationPrincipal CustomUserDet
return ResponseEntity.status(HttpStatus.CREATED).body(flightId);
}


/** 항공권 나의 좋아요 목록 불러오기 API **/
@GetMapping("/likes")
public ResponseEntity<List<FlightLikeResponse>> getLikedFlights(@AuthenticationPrincipal CustomUserDetails customUserDetails) {
Expand All @@ -71,6 +68,7 @@ public ResponseEntity<List<FlightLikeResponse>> getLikedFlights(@AuthenticationP
return ResponseEntity.ok(likedFlights);
}


/** 항공권 나의 좋아요 삭제 API **/
@DeleteMapping("/like/{id}")
public ResponseEntity<Void> deleteLikeFlight(@AuthenticationPrincipal CustomUserDetails customUserDetails,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -112,7 +111,6 @@ private String buildChildrenParam(int count) {

/**
* 항공권 좋아요 저장
*
**/
@Override
@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ public ResponseEntity<String> authRecreate(@RequestBody AuthRecreateRequest auth
/** 멤버 정보 조회 **/
@GetMapping("/information")
public ResponseEntity<MemberDetailResponse> getMemberInfo(@AuthenticationPrincipal CustomUserDetails customUserDetails) {

return ResponseEntity.ok(memberService.getMemberInfo(customUserDetails.getUsername()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -99,7 +99,7 @@ public void signUp(SignUpRequest signUpRequest, String memberUid) {
public ResponseEntity<String> authRecreate(AuthRecreateRequest authRecreateRequest) {

if (!tokenProvider.validateRefreshToken(authRecreateRequest.getRefreshToken())) {
throw new AuthenticationFailedException();
throw new RefreshTokenInvalidException();
}
String uid = tokenProvider.getUid(authRecreateRequest.getRefreshToken());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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", "리프레시 토큰이 유효하지 않습니다."),

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.isp.backend.global.exception.member;
package com.isp.backend.global.exception.common;

import com.isp.backend.global.exception.CustomException;
import com.isp.backend.global.exception.ErrorCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -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);}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.isp.backend.global.exception.member;
package com.isp.backend.global.exception.common;

import com.isp.backend.global.exception.CustomException;
import com.isp.backend.global.exception.ErrorCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.isp.backend.global.exception.member;
package com.isp.backend.global.exception.common;

import com.isp.backend.global.exception.CustomException;
import com.isp.backend.global.exception.ErrorCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.isp.backend.global.exception.member;
package com.isp.backend.global.exception.common;

import com.isp.backend.global.exception.CustomException;
import com.isp.backend.global.exception.ErrorCode;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,5 @@ public void handle(HttpServletRequest request, HttpServletResponse response, Acc
// 인가되지 않은(권한이 없는) 요청이 들어왔을 때의 처리를 담당 - `handle` 메서드는 예외 처리 및 로깅을 수행한다.
log.error("Forbidden Request : {}", request.getRequestURI());
response.sendError(HttpServletResponse.SC_FORBIDDEN);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -13,6 +14,7 @@

import java.io.IOException;

@Slf4j
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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<? extends GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));

return new UsernamePasswordAuthenticationToken(userDetails, token, authorities);
}


// Access Token 검증
public boolean validateAccessToken(String accessToken) {
try {
Expand Down Expand Up @@ -144,7 +148,7 @@ public boolean validateRefreshToken(String refreshToken) {
return false;
}


// 토큰에서 uid 가져오기
public String getUid(String token) {
return parseClaims(token).getSubject();
}
Expand All @@ -158,6 +162,7 @@ private Claims parseClaims(String token) {
.getBody();
}

// 토큰 만료 시간 가져오기
private Date getExpirationTime(Long expirationTime) {
return new Date((new Date()).getTime() + expirationTime);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -24,7 +25,7 @@ public String getUsername() { //유저 이메일 가져오기

@Override
public String getPassword() {
return member.getUid();
return null; // 패스워드가 없으므로 null 반환
}

@Override
Expand All @@ -49,7 +50,7 @@ public boolean isEnabled() {

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.emptyList();
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
}

}
Loading
Loading