diff --git a/src/main/java/com/wayble/server/auth/exception/AuthErrorCase.java b/src/main/java/com/wayble/server/auth/exception/AuthErrorCase.java new file mode 100644 index 0000000..ae589b4 --- /dev/null +++ b/src/main/java/com/wayble/server/auth/exception/AuthErrorCase.java @@ -0,0 +1,15 @@ +package com.wayble.server.auth.exception; + +import com.wayble.server.common.exception.ErrorCase; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum AuthErrorCase implements ErrorCase { + UNAUTHORIZED(401, 1001, "인증 정보가 없거나 userId를 추출할 수 없습니다."); + + private final Integer httpStatusCode; + private final Integer errorCode; + private final String message; +} diff --git a/src/main/java/com/wayble/server/auth/resolver/CurrentUserArgumentResolver.java b/src/main/java/com/wayble/server/auth/resolver/CurrentUserArgumentResolver.java index 091bad7..cdb7e40 100644 --- a/src/main/java/com/wayble/server/auth/resolver/CurrentUserArgumentResolver.java +++ b/src/main/java/com/wayble/server/auth/resolver/CurrentUserArgumentResolver.java @@ -1,17 +1,26 @@ package com.wayble.server.auth.resolver; +import com.wayble.server.auth.exception.AuthErrorCase; +import com.wayble.server.common.config.security.jwt.JwtTokenProvider; +import com.wayble.server.common.exception.ApplicationException; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; import org.springframework.core.MethodParameter; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; @Component +@RequiredArgsConstructor public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver { + private final JwtTokenProvider jwtTokenProvider; + @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(CurrentUser.class) @@ -19,27 +28,38 @@ public boolean supportsParameter(MethodParameter parameter) { } @Override - public Object resolveArgument(MethodParameter parameter, - ModelAndViewContainer mav, - NativeWebRequest webRequest, - WebDataBinderFactory binderFactory) { + public Object resolveArgument( + MethodParameter parameter, + ModelAndViewContainer mav, + NativeWebRequest webRequest, + WebDataBinderFactory binderFactory + ) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - if (auth == null) { - throw new IllegalStateException("인증 정보가 없습니다."); + if (auth != null) { + Object principal = auth.getPrincipal(); + if (principal instanceof Long l) { return l; } + if (principal instanceof Integer i) { return i.longValue(); } + if (principal instanceof String s && s.chars().allMatch(Character::isDigit)) { + return Long.parseLong(s); + } + String name = auth.getName(); + if (name != null && name.chars().allMatch(Character::isDigit)) { + return Long.parseLong(name); + } } - Object principal = auth.getPrincipal(); - if (principal instanceof Long l) return l; - if (principal instanceof Integer i) return i.longValue(); - if (principal instanceof String s) { + HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); + String authz = request != null ? request.getHeader("Authorization") : null; + if (StringUtils.hasText(authz) && authz.startsWith("Bearer ")) { + String token = authz.substring(7); try { - return Long.parseLong(s); - } catch (NumberFormatException ignored) {} - } - try { - return Long.parseLong(auth.getName()); - } catch (Exception e) { - throw new IllegalStateException("userId를 추출할 수 없습니다.", e); + Long userId = jwtTokenProvider.getUserId(token); + if (userId != null) { return userId; } + } catch (IllegalArgumentException e) { + throw new ApplicationException(AuthErrorCase.UNAUTHORIZED); + } } + + throw new ApplicationException(AuthErrorCase.UNAUTHORIZED); } } \ No newline at end of file diff --git a/src/main/java/com/wayble/server/review/controller/ReviewController.java b/src/main/java/com/wayble/server/review/controller/ReviewController.java index 1661a7c..840b780 100644 --- a/src/main/java/com/wayble/server/review/controller/ReviewController.java +++ b/src/main/java/com/wayble/server/review/controller/ReviewController.java @@ -13,7 +13,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; - +import io.swagger.v3.oas.annotations.Parameter; import java.util.List; @@ -37,7 +37,7 @@ public class ReviewController { }) public CommonResponse registerReview( @PathVariable Long waybleZoneId, - @CurrentUser Long userId, + @Parameter(hidden = true) @CurrentUser Long userId, @RequestBody @Valid ReviewRegisterDto dto ) { reviewService.registerReview(waybleZoneId, userId, dto); diff --git a/src/main/java/com/wayble/server/user/controller/UserPlaceController.java b/src/main/java/com/wayble/server/user/controller/UserPlaceController.java index 5dc568a..8401614 100644 --- a/src/main/java/com/wayble/server/user/controller/UserPlaceController.java +++ b/src/main/java/com/wayble/server/user/controller/UserPlaceController.java @@ -9,6 +9,7 @@ import com.wayble.server.user.service.UserPlaceService; import com.wayble.server.wayblezone.dto.WaybleZoneListResponseDto; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.validation.Valid; @@ -34,7 +35,7 @@ public class UserPlaceController { @ApiResponse(responseCode = "403", description = "권한이 없습니다.") }) public CommonResponse saveUserPlace( - @CurrentUser Long userId, + @Parameter(hidden = true) @CurrentUser Long userId, @RequestBody @Valid UserPlaceRequestDto request ) { userPlaceService.saveUserPlace(userId, request); // userId 파라미터로 넘김 @@ -49,7 +50,7 @@ public CommonResponse saveUserPlace( @ApiResponse(responseCode = "403", description = "권한이 없습니다.") }) public CommonResponse> getMyPlaceSummaries( - @CurrentUser Long userId, + @Parameter(hidden = true) @CurrentUser Long userId, @RequestParam(name = "sort", defaultValue = "latest") String sort ) { List summaries = userPlaceService.getMyPlaceSummaries(userId, sort); @@ -66,7 +67,7 @@ public CommonResponse> getMyPlaceSummaries( @ApiResponse(responseCode = "403", description = "권한이 없습니다.") }) public CommonResponse> getZonesInPlace( - @CurrentUser Long userId, + @Parameter(hidden = true) @CurrentUser Long userId, @RequestParam Long placeId, @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "20") Integer size @@ -86,7 +87,7 @@ public CommonResponse> getZonesInPlace( @ApiResponse(responseCode = "403", description = "권한이 없습니다.") }) public CommonResponse removeZoneFromPlace( - @CurrentUser Long userId, + @Parameter(hidden = true) @CurrentUser Long userId, @RequestBody @Valid UserPlaceRemoveRequestDto request ) { userPlaceService.removeZoneFromPlace(userId, request.placeId(), request.waybleZoneId()); diff --git a/src/test/java/com/wayble/server/review/service/ReviewServiceTest.java b/src/test/java/com/wayble/server/review/service/ReviewServiceTest.java index 41fd9b8..b652631 100644 --- a/src/test/java/com/wayble/server/review/service/ReviewServiceTest.java +++ b/src/test/java/com/wayble/server/review/service/ReviewServiceTest.java @@ -66,7 +66,7 @@ void t1() { assertEquals(4.5, ratingCaptor.getValue(), 1e-6); - verify(zone, times(1)).addReviewCount(1L); + verify(zone, times(1)).addReviewCount(1); verify(reviewImageRepository, times(1)).save(any(ReviewImage.class)); verify(waybleZoneRepository, times(1)).save(zone); }