From 13b0de16e968c6220f4676c787f8f46f0a0249d6 Mon Sep 17 00:00:00 2001 From: pricelees Date: Sun, 13 Jul 2025 20:48:05 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20AuthController=20=EC=BD=94=ED=8B=80?= =?UTF-8?q?=EB=A6=B0=20=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - API Docs 관련 정보를 담고 있는 AuthAPI 추가 및 구현 - CookieUtils를 사용하여 불필요한 컨트롤러 로직 제거 --- .../roomescape/system/auth/web/AuthAPI.kt | 67 +++++++++ .../system/auth/web/AuthController.kt | 132 ++++++------------ 2 files changed, 110 insertions(+), 89 deletions(-) create mode 100644 src/main/java/roomescape/system/auth/web/AuthAPI.kt diff --git a/src/main/java/roomescape/system/auth/web/AuthAPI.kt b/src/main/java/roomescape/system/auth/web/AuthAPI.kt new file mode 100644 index 00000000..27dd2ecd --- /dev/null +++ b/src/main/java/roomescape/system/auth/web/AuthAPI.kt @@ -0,0 +1,67 @@ +package roomescape.system.auth.web + +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.Parameter +import io.swagger.v3.oas.annotations.media.Content +import io.swagger.v3.oas.annotations.media.Schema +import io.swagger.v3.oas.annotations.responses.ApiResponse +import io.swagger.v3.oas.annotations.responses.ApiResponses +import io.swagger.v3.oas.annotations.tags.Tag +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import jakarta.validation.Valid +import org.springframework.http.HttpStatus +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.ResponseStatus +import roomescape.system.auth.web.support.LoginRequired +import roomescape.system.auth.web.support.MemberId +import roomescape.system.dto.response.ErrorResponse +import roomescape.system.dto.response.RoomEscapeApiResponse + +@Tag(name = "1. 인증 / 인가 API", description = "로그인, 로그아웃 및 로그인 상태를 확인합니다") +interface AuthAPI { + + @ResponseStatus(HttpStatus.OK) + @Operation(summary = "로그인") + @ApiResponses( + ApiResponse( + responseCode = "200", + description = "로그인 성공시 쿠키에 토큰 정보를 저장합니다." + ), + ApiResponse( + responseCode = "400", + description = "존재하지 않는 회원이거나, 이메일 또는 비밀번호가 잘못 입력되었습니다.", + content = [Content(schema = Schema(implementation = ErrorResponse::class))] + ) + ) + fun login( + @Valid @RequestBody loginRequest: LoginRequest, + response: HttpServletResponse + ): RoomEscapeApiResponse + + @ResponseStatus(HttpStatus.OK) + @Operation(summary = "로그인 상태 확인") + @ApiResponses( + ApiResponse( + responseCode = "200", + description = "로그인 상태이며, 로그인된 회원의 이름을 반환합니다." + ), + ApiResponse( + responseCode = "400", + description = "쿠키에 있는 토큰 정보로 회원을 조회할 수 없습니다.", + content = [Content(schema = Schema(implementation = ErrorResponse::class))] + ), + ApiResponse( + responseCode = "401", + description = "토큰 정보가 없거나, 만료되었습니다.", + content = [Content(schema = Schema(implementation = ErrorResponse::class))] + ) + ) + fun checkLogin(@MemberId @Parameter(hidden = true) memberId: Long): RoomEscapeApiResponse + + @LoginRequired + @ResponseStatus(HttpStatus.OK) + @Operation(summary = "로그아웃", tags = ["로그인이 필요한 API"]) + @ApiResponses(ApiResponse(responseCode = "200", description = "로그아웃 성공시 쿠키에 저장된 토큰 정보를 삭제합니다.")) + fun logout(request: HttpServletRequest, response: HttpServletResponse): RoomEscapeApiResponse +} diff --git a/src/main/java/roomescape/system/auth/web/AuthController.kt b/src/main/java/roomescape/system/auth/web/AuthController.kt index d7e72f5a..2008a124 100644 --- a/src/main/java/roomescape/system/auth/web/AuthController.kt +++ b/src/main/java/roomescape/system/auth/web/AuthController.kt @@ -1,100 +1,54 @@ -package roomescape.system.auth.web; +package roomescape.system.auth.web -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; -import roomescape.system.auth.web.support.LoginRequired; -import roomescape.system.auth.web.support.MemberId; -import roomescape.system.auth.infrastructure.jwt.TokenDto; -import roomescape.system.auth.service.AuthService; -import roomescape.system.dto.response.ErrorResponse; -import roomescape.system.dto.response.RoomEscapeApiResponse; +import io.swagger.v3.oas.annotations.Parameter +import jakarta.servlet.http.Cookie +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import jakarta.validation.Valid +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RestController +import roomescape.system.auth.service.AuthService +import roomescape.system.auth.web.support.* +import roomescape.system.dto.response.RoomEscapeApiResponse @RestController -@Tag(name = "1. 인증 / 인가 API", description = "로그인, 로그아웃 및 로그인 상태를 확인합니다") -public class AuthController { +class AuthController( + private val authService: AuthService +) : AuthAPI { - private final AuthService authService; + @PostMapping("/login") + override fun login( + @Valid @RequestBody loginRequest: LoginRequest, + response: HttpServletResponse + ): RoomEscapeApiResponse { + val accessToken: TokenResponse = authService.login(loginRequest) + val cookie: Cookie = accessToken.toCookie() - public AuthController(AuthService authService) { - this.authService = authService; - } + response.addAccessTokenCookie(cookie) - @PostMapping("/login") - @ResponseStatus(HttpStatus.OK) - @Operation(summary = "로그인") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "로그인 성공시 쿠키에 토큰 정보를 저장합니다."), - @ApiResponse(responseCode = "400", description = "존재하지 않는 회원이거나, 이메일 또는 비밀번호가 잘못 입력되었습니다.", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))) - }) - public RoomEscapeApiResponse login( - @Valid @RequestBody LoginRequest loginRequest, - HttpServletResponse response - ) { - TokenDto tokenInfo = authService.login(loginRequest); - addCookieToResponse(new Cookie("accessToken", tokenInfo.accessToken()), response); - return RoomEscapeApiResponse.success(); - } + return RoomEscapeApiResponse.success() + } - @GetMapping("/login/check") - @ResponseStatus(HttpStatus.OK) - @Operation(summary = "로그인 상태 확인") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "로그인 상태이며, 로그인된 회원의 이름을 반환합니다."), - @ApiResponse(responseCode = "400", description = "쿠키에 있는 토큰 정보로 회원을 조회할 수 없습니다.", - content = @Content(schema = @Schema(implementation = ErrorResponse.class))), - }) - public RoomEscapeApiResponse checkLogin(@MemberId @Parameter(hidden = true) Long memberId) { - LoginCheckResponse response = authService.checkLogin(memberId); - return RoomEscapeApiResponse.success(response); - } + @GetMapping("/login/check") + override fun checkLogin( + @MemberId @Parameter(hidden = true) memberId: Long + ): RoomEscapeApiResponse { + val response = authService.checkLogin(memberId) - @LoginRequired - @PostMapping("/logout") - @ResponseStatus(HttpStatus.OK) - @Operation(summary = "로그아웃", tags = "로그인이 필요한 API") - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "로그아웃 성공시 쿠키에 저장된 토큰 정보를 삭제합니다.") - }) - public RoomEscapeApiResponse logout( - HttpServletRequest request, - HttpServletResponse response - ) { - Cookie cookie = getTokenCookie(request); - cookie.setValue(null); - cookie.setMaxAge(0); - addCookieToResponse(cookie, response); - return RoomEscapeApiResponse.success(); - } + return RoomEscapeApiResponse.success(response) + } - private Cookie getTokenCookie(HttpServletRequest request) { - for (Cookie cookie : request.getCookies()) { - if (cookie.getName().equals("accessToken")) { - return cookie; - } - } - return new Cookie("accessToken", null); - } + @PostMapping("/logout") + override fun logout( + request: HttpServletRequest, + response: HttpServletResponse + ): RoomEscapeApiResponse { + val cookie: Cookie = request.accessTokenCookie() + cookie.expire() + response.addAccessTokenCookie(cookie) - private void addCookieToResponse(Cookie cookie, HttpServletResponse response) { - cookie.setHttpOnly(true); - - response.addCookie(cookie); - } + return RoomEscapeApiResponse.success() + } }