Skip to content

Commit 3ab83e1

Browse files
authored
Merge pull request #79 from prgrms-web-devcourse-final-project/feat/be/78
feat(be) : security 리팩토링
2 parents 56dba42 + 37a075e commit 3ab83e1

File tree

6 files changed

+41
-18
lines changed

6 files changed

+41
-18
lines changed

src/main/kotlin/com/back/koreaTravelGuide/common/exception/GlobalExceptionHandler.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler
1414
* @Valid 검증 실패 → 400
1515
* throw IllegalArgumentException("메시지") → 400
1616
* throw NoSuchElementException("메시지") → 404
17+
* throw IllegalStateException("메시지") → 409
1718
* 기타 모든 예외 → 500
1819
*/
1920
@ControllerAdvice
@@ -41,6 +42,12 @@ class GlobalExceptionHandler {
4142
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ApiResponse(ex.message ?: "데이터를 찾을 수 없습니다"))
4243
}
4344

45+
@ExceptionHandler(IllegalStateException::class)
46+
fun handleIllegalState(ex: IllegalStateException): ResponseEntity<ApiResponse<Void>> {
47+
logger.warn("부적절한 상태: {}", ex.message)
48+
return ResponseEntity.status(HttpStatus.CONFLICT).body(ApiResponse(ex.message ?: "요청을 처리할 수 없는 상태입니다"))
49+
}
50+
4451
@ExceptionHandler(Exception::class)
4552
fun handleGenericException(
4653
ex: Exception,
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.back.koreaTravelGuide.common.security
2+
3+
import org.springframework.security.core.Authentication
4+
5+
fun Authentication.getUserId(): Long {
6+
if (principal is Long) {
7+
return principal as Long
8+
}
9+
throw IllegalStateException("인증된 사용자 ID를 찾을 수 없거나 타입이 올바르지 않습니다.")
10+
}

src/main/kotlin/com/back/koreaTravelGuide/domain/auth/controller/AuthController.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.back.koreaTravelGuide.domain.auth.controller
22

33
import com.back.koreaTravelGuide.common.ApiResponse
4+
import com.back.koreaTravelGuide.common.security.getUserId
45
import com.back.koreaTravelGuide.domain.auth.dto.request.UserRoleUpdateRequest
56
import com.back.koreaTravelGuide.domain.auth.dto.response.AccessTokenResponse
67
import com.back.koreaTravelGuide.domain.auth.dto.response.LoginResponse
@@ -10,7 +11,7 @@ import jakarta.servlet.http.HttpServletRequest
1011
import jakarta.servlet.http.HttpServletResponse
1112
import org.springframework.beans.factory.annotation.Value
1213
import org.springframework.http.ResponseEntity
13-
import org.springframework.security.core.annotation.AuthenticationPrincipal
14+
import org.springframework.security.core.Authentication
1415
import org.springframework.web.bind.annotation.CookieValue
1516
import org.springframework.web.bind.annotation.PostMapping
1617
import org.springframework.web.bind.annotation.RequestBody
@@ -45,9 +46,10 @@ class AuthController(
4546
@Operation(summary = "신규 사용자 역할 선택")
4647
@PostMapping("/role")
4748
fun updateUserRole(
48-
@AuthenticationPrincipal userId: Long,
49+
authentication: Authentication,
4950
@RequestBody request: UserRoleUpdateRequest,
5051
): ResponseEntity<ApiResponse<LoginResponse>> {
52+
val userId = authentication.getUserId()
5153
val loginResponse = authService.updateRoleAndLogin(userId, request.role)
5254
return ResponseEntity.ok(ApiResponse("역할이 선택되었으며 로그인에 성공했습니다.", loginResponse))
5355
}

src/main/kotlin/com/back/koreaTravelGuide/domain/rate/controller/RateController.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.back.koreaTravelGuide.domain.rate.controller
22

33
import com.back.koreaTravelGuide.common.ApiResponse
4+
import com.back.koreaTravelGuide.common.security.getUserId
45
import com.back.koreaTravelGuide.domain.rate.dto.GuideRatingSummaryResponse
56
import com.back.koreaTravelGuide.domain.rate.dto.RateRequest
67
import com.back.koreaTravelGuide.domain.rate.dto.RateResponse
@@ -10,7 +11,7 @@ import org.springframework.data.domain.Page
1011
import org.springframework.data.domain.Pageable
1112
import org.springframework.http.ResponseEntity
1213
import org.springframework.security.access.prepost.PreAuthorize
13-
import org.springframework.security.core.annotation.AuthenticationPrincipal
14+
import org.springframework.security.core.Authentication
1415
import org.springframework.web.bind.annotation.GetMapping
1516
import org.springframework.web.bind.annotation.PathVariable
1617
import org.springframework.web.bind.annotation.PutMapping
@@ -26,31 +27,32 @@ class RateController(
2627
@Operation(summary = "가이드 평가 생성/수정")
2728
@PutMapping("/guides/{guideId}")
2829
fun rateGuide(
29-
@AuthenticationPrincipal raterUserId: Long,
30+
authentication: Authentication,
3031
@PathVariable guideId: Long,
3132
@RequestBody request: RateRequest,
3233
): ResponseEntity<ApiResponse<RateResponse>> {
34+
val raterUserId = authentication.getUserId()
3335
val rate = rateService.rateGuide(raterUserId, guideId, request.rating, request.comment)
3436
return ResponseEntity.ok(ApiResponse("가이드 평가가 등록되었습니다.", RateResponse.from(rate)))
3537
}
3638

3739
@Operation(summary = "AI 채팅 세션 평가 생성/수정")
3840
@PutMapping("/aichat/sessions/{sessionId}")
3941
fun rateAiSession(
40-
@AuthenticationPrincipal raterUserId: Long,
42+
authentication: Authentication,
4143
@PathVariable sessionId: Long,
4244
@RequestBody request: RateRequest,
4345
): ResponseEntity<ApiResponse<RateResponse>> {
46+
val raterUserId = authentication.getUserId()
4447
val rate = rateService.rateAiSession(raterUserId, sessionId, request.rating, request.comment)
4548
return ResponseEntity.ok(ApiResponse("AI 채팅 평가가 등록되었습니다.", RateResponse.from(rate)))
4649
}
4750

4851
@Operation(summary = "내가 받은 가이드 평가 조회")
4952
@GetMapping("/guides/my")
5053
@PreAuthorize("hasRole('GUIDE')")
51-
fun getMyGuideRatings(
52-
@AuthenticationPrincipal guideId: Long,
53-
): ResponseEntity<ApiResponse<GuideRatingSummaryResponse>> {
54+
fun getMyGuideRatings(authentication: Authentication): ResponseEntity<ApiResponse<GuideRatingSummaryResponse>> {
55+
val guideId = authentication.getUserId()
5456
val summary = rateService.getMyGuideRatingSummary(guideId)
5557
return ResponseEntity.ok(ApiResponse("내 가이드 평점 정보를 조회했습니다.", summary))
5658
}

src/main/kotlin/com/back/koreaTravelGuide/domain/user/controller/GuideController.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package com.back.koreaTravelGuide.domain.guide.controller
22

33
import com.back.koreaTravelGuide.common.ApiResponse
4+
import com.back.koreaTravelGuide.common.security.getUserId
45
import com.back.koreaTravelGuide.domain.guide.service.GuideService
56
import com.back.koreaTravelGuide.domain.user.dto.request.GuideUpdateRequest
67
import com.back.koreaTravelGuide.domain.user.dto.response.GuideResponse
78
import io.swagger.v3.oas.annotations.Operation
89
import io.swagger.v3.oas.annotations.tags.Tag
910
import org.springframework.http.ResponseEntity
1011
import org.springframework.security.access.prepost.PreAuthorize
11-
import org.springframework.security.core.annotation.AuthenticationPrincipal
12+
import org.springframework.security.core.Authentication
1213
import org.springframework.web.bind.annotation.GetMapping
1314
import org.springframework.web.bind.annotation.PatchMapping
1415
import org.springframework.web.bind.annotation.PathVariable
@@ -42,9 +43,10 @@ class GuideController(
4243
@PreAuthorize("hasRole('GUIDE')")
4344
@PatchMapping("/me")
4445
fun updateMyGuideProfile(
45-
@AuthenticationPrincipal guideId: Long,
46+
authentication: Authentication,
4647
@RequestBody request: GuideUpdateRequest,
4748
): ResponseEntity<ApiResponse<GuideResponse>> {
49+
val guideId = authentication.getUserId()
4850
val updatedGuideProfile = guideService.updateGuideProfile(guideId, request)
4951
return ResponseEntity.ok(ApiResponse("가이드 정보가 성공적으로 수정되었습니다.", updatedGuideProfile))
5052
}

src/main/kotlin/com/back/koreaTravelGuide/domain/user/controller/UserController.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package com.back.koreaTravelGuide.domain.user.controller
22

33
import com.back.koreaTravelGuide.common.ApiResponse
4+
import com.back.koreaTravelGuide.common.security.getUserId
45
import com.back.koreaTravelGuide.domain.user.dto.request.UserUpdateRequest
56
import com.back.koreaTravelGuide.domain.user.dto.response.UserResponse
67
import com.back.koreaTravelGuide.domain.user.service.UserService
78
import io.swagger.v3.oas.annotations.Operation
89
import org.springframework.http.ResponseEntity
9-
import org.springframework.security.core.annotation.AuthenticationPrincipal
10+
import org.springframework.security.core.Authentication
1011
import org.springframework.web.bind.annotation.DeleteMapping
1112
import org.springframework.web.bind.annotation.GetMapping
1213
import org.springframework.web.bind.annotation.PatchMapping
@@ -21,28 +22,27 @@ class UserController(
2122
) {
2223
@Operation(summary = "내 정보 조회")
2324
@GetMapping("/me")
24-
fun getMyProfile(
25-
@AuthenticationPrincipal userId: Long,
26-
): ResponseEntity<ApiResponse<UserResponse>> {
25+
fun getMyProfile(authentication: Authentication): ResponseEntity<ApiResponse<UserResponse>> {
26+
val userId = authentication.getUserId()
2727
val userProfile = userService.getUserProfileById(userId)
2828
return ResponseEntity.ok(ApiResponse("내 정보를 성공적으로 조회했습니다.", userProfile))
2929
}
3030

3131
@Operation(summary = "내 프로필 수정")
3232
@PatchMapping("/me")
3333
fun updateMyProfile(
34-
@AuthenticationPrincipal userId: Long,
34+
authentication: Authentication,
3535
@RequestBody request: UserUpdateRequest,
3636
): ResponseEntity<ApiResponse<UserResponse>> {
37+
val userId = authentication.getUserId()
3738
val updatedProfile = userService.updateUserProfile(userId, request)
3839
return ResponseEntity.ok(ApiResponse("정보가 성공적으로 수정되었습니다.", updatedProfile))
3940
}
4041

4142
@Operation(summary = "회원 탈퇴")
4243
@DeleteMapping("/me")
43-
fun deleteMe(
44-
@AuthenticationPrincipal userId: Long,
45-
): ResponseEntity<ApiResponse<Unit>> {
44+
fun deleteMe(authentication: Authentication): ResponseEntity<ApiResponse<Unit>> {
45+
val userId = authentication.getUserId()
4646
userService.deleteUser(userId)
4747
return ResponseEntity.ok(ApiResponse("회원 탈퇴가 완료되었습니다."))
4848
}

0 commit comments

Comments
 (0)