From 7b10ef0db8fa73a96edeb91c4e179ec4f91ddeca Mon Sep 17 00:00:00 2001 From: sdw086 Date: Fri, 22 May 2026 11:55:48 +0900 Subject: [PATCH] =?UTF-8?q?[api]=20SsoController.java,=20AuthController.ja?= =?UTF-8?q?va=20=EC=BB=A8=EB=B2=A4=EC=85=98=20=EB=A7=9E=EC=B6=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/modules/auth/AuthController.java | 110 ++++++------- .../alist/api/modules/auth/SsoController.java | 111 ++++++------- .../api/modules/auth/dto/AuthTokenDto.java | 24 +++ .../api/modules/auth/dto/SsoLoginDto.java | 2 +- ...oginForm.java => AuthApiKeyLoginForm.java} | 12 +- .../api/modules/auth/form/AuthTokenForm.java | 24 +++ .../modules/auth/form/SsoExchangeForm.java | 14 +- .../api/modules/auth/form/SsoLoginForm.java | 14 +- .../api/modules/auth/form/TokenForm.java | 24 --- .../api/modules/auth/mapper/AuthMapper.java | 3 +- .../api/modules/auth/service/AuthService.java | 154 +++++++++++------- .../api/modules/auth/service/SsoService.java | 84 +++++----- .../api/modules/auth/vo/AuthAccessVo.java | 27 +++ .../modules/auth/vo/AuthApiKeyLoginVo.java | 24 +++ .../api/modules/auth/vo/AuthRefreshVo.java | 22 +++ .../TokenDto.java => vo/AuthTokenVo.java} | 8 +- .../alist/api/modules/auth/vo/LoginVo.java | 12 ++ .../api/modules/auth/vo/SsoExchangeVo.java | 34 ++++ .../modules/auth/vo/SsoLoginCheckedVo.java | 40 +++++ .../SsoLoginVo.java} | 21 ++- .../api/modules/auth/vo/SsoLogoutVo.java | 13 ++ .../alist/api/modules/auth/vo/TokenVo.java | 22 --- .../resources/mapper/auth/LoginMapper.xml | 2 +- 23 files changed, 508 insertions(+), 293 deletions(-) create mode 100644 src/main/java/com/alist/api/modules/auth/dto/AuthTokenDto.java rename src/main/java/com/alist/api/modules/auth/form/{ApikeyLoginForm.java => AuthApiKeyLoginForm.java} (60%) create mode 100644 src/main/java/com/alist/api/modules/auth/form/AuthTokenForm.java delete mode 100644 src/main/java/com/alist/api/modules/auth/form/TokenForm.java create mode 100644 src/main/java/com/alist/api/modules/auth/vo/AuthAccessVo.java create mode 100644 src/main/java/com/alist/api/modules/auth/vo/AuthApiKeyLoginVo.java create mode 100644 src/main/java/com/alist/api/modules/auth/vo/AuthRefreshVo.java rename src/main/java/com/alist/api/modules/auth/{dto/TokenDto.java => vo/AuthTokenVo.java} (84%) create mode 100644 src/main/java/com/alist/api/modules/auth/vo/SsoExchangeVo.java create mode 100644 src/main/java/com/alist/api/modules/auth/vo/SsoLoginCheckedVo.java rename src/main/java/com/alist/api/modules/auth/{dto/SsoLoginCheckDto.java => vo/SsoLoginVo.java} (62%) create mode 100644 src/main/java/com/alist/api/modules/auth/vo/SsoLogoutVo.java delete mode 100644 src/main/java/com/alist/api/modules/auth/vo/TokenVo.java diff --git a/src/main/java/com/alist/api/modules/auth/AuthController.java b/src/main/java/com/alist/api/modules/auth/AuthController.java index f8afa1a..666724d 100644 --- a/src/main/java/com/alist/api/modules/auth/AuthController.java +++ b/src/main/java/com/alist/api/modules/auth/AuthController.java @@ -4,14 +4,12 @@ import com.alist.api.common.response.ApiResponse; import com.alist.api.common.response.ApiResponseCode; import com.alist.api.common.utils.SessionUtil; import com.alist.api.config.jwt.JwtTokenProvider; -import com.alist.api.modules.auth.dto.SsoExchangeDto; import com.alist.api.modules.auth.dto.LoginDto; -import com.alist.api.modules.auth.dto.TokenDto; -import com.alist.api.modules.auth.form.ApikeyLoginForm; -import com.alist.api.modules.auth.form.TokenForm; -import com.alist.api.modules.auth.service.SsoService; +import com.alist.api.modules.auth.form.AuthApiKeyLoginForm; +import com.alist.api.modules.auth.form.AuthTokenForm; import com.alist.api.modules.auth.service.AuthService; -import com.alist.api.modules.auth.vo.TokenVo; +import com.alist.api.modules.auth.service.SsoService; +import com.alist.api.modules.auth.vo.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; @@ -21,9 +19,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.HashMap; -import java.util.Map; - @Tag(name = "102. 엑세스 토큰 발급", description = "엑세스 토큰 발급") @RestController @RequestMapping("/auth") @@ -55,93 +50,96 @@ public class AuthController { public AuthController(SsoService ssoService, JwtTokenProvider jwtTokenProvider, AuthService authService) { this.ssoService = ssoService; this.jwtTokenProvider = jwtTokenProvider; - this.authService = authService; - } - - @Operation( - summary = "엑세스 토큰 발급 (테스트용 실사용X)", - description = "엑세스 토큰이 발급됩니다. (테스트용 실사용X)" - ) - @PostMapping("/token") - public ResponseEntity> token(@Valid @RequestBody TokenForm tokenForm) { - TokenVo tokenVo = new TokenVo(); - tokenVo.setAccessToken(jwtTokenProvider.createToken(tokenForm.toTokenDto().getId())); - - return ApiResponse.entity(tokenVo, ApiResponseCode.CODE_2001, "엑세스 토큰"); + this.authService = authService; } @Operation( - summary = "SSO 기반 토큰 발급", - description = "ALIST_SSO 쿠키 기준으로 SSO 로그인 상태를 확인한 뒤 accessToken, refreshToken 쿠키를 발급합니다." + summary = "엑세스 토큰 발급 (테스트용 실사용X)" + , description = "엑세스 토큰이 발급됩니다. (테스트용 실사용X)" + ) + @PostMapping("/token") + public ResponseEntity> authToken(@Valid @RequestBody AuthTokenForm authTokenForm) { + AuthTokenVo authTokenVo = new AuthTokenVo(); + authTokenVo.setAccessToken(jwtTokenProvider.createToken(authTokenForm.toDto().getId())); + + return ApiResponse.entity(authTokenVo, ApiResponseCode.CODE_2001, "엑세스 토큰"); + } + + @Operation( + summary = "SSO 기반 토큰 발급" + , description = "ALIST_SSO 쿠키 기준으로 SSO 로그인 상태를 확인한 뒤 accessToken, refreshToken 쿠키를 발급합니다." ) @PostMapping("/access") - public ResponseEntity>> access( + public ResponseEntity> authAccess( HttpServletRequest request, HttpServletResponse response ) { String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName); - SsoExchangeDto ssoSession = ssoService.loginChecked(ssoSessionId); + SsoExchangeVo ssoExchangeVo = ssoService.selectSsoLoginChecked(ssoSessionId); - if (ssoSession == null) { - return ApiResponse.entity(Map.of("isAccessToken", false), ApiResponseCode.CODE_401); + AuthAccessVo authAccessVo = new AuthAccessVo(); + + if (ssoExchangeVo == null) { + authAccessVo.setAccessToken(false); + return ApiResponse.entity(authAccessVo, ApiResponseCode.CODE_401); } - String accessToken = jwtTokenProvider.createAccessToken(ssoSession.getUserTokenIdx(), ssoSession.getUserRole()); - String refreshToken = jwtTokenProvider.createRefreshToken(ssoSession.getUserTokenIdx()); + String accessToken = jwtTokenProvider.createAccessToken(ssoExchangeVo.getUserTokenIdx(), ssoExchangeVo.getUserRole()); + String refreshToken = jwtTokenProvider.createRefreshToken(ssoExchangeVo.getUserTokenIdx()); LoginDto loginDto = new LoginDto(); - loginDto.setUserTokenIdx(ssoSession.getUserTokenIdx()); + loginDto.setUserTokenIdx(ssoExchangeVo.getUserTokenIdx()); loginDto.setRefreshToken(refreshToken); authService.updateRefreshToken(loginDto); SessionUtil.addTokenCookie(response, "accessToken", accessToken, cookieDomain, cookieSecure, cookieSameSite, accessTokenValiditySeconds); - SessionUtil.addTokenCookie(response,"refreshToken", refreshToken, cookieDomain, cookieSecure, cookieSameSite, refreshTokenValiditySeconds); + SessionUtil.addTokenCookie(response, "refreshToken", refreshToken, cookieDomain, cookieSecure, cookieSameSite, refreshTokenValiditySeconds); - Map result = new HashMap<>(); - result.put("isAccessToken", true); - result.put("userIdx", ssoSession.getUserIdx()); - result.put("userId", ssoSession.getUserId()); - result.put("userRole", ssoSession.getUserRole()); - result.put("userType", ssoSession.getUserType()); + authAccessVo.setAccessToken(true); + authAccessVo.setUserIdx(ssoExchangeVo.getUserIdx()); + authAccessVo.setUserId(ssoExchangeVo.getUserId()); + authAccessVo.setUserRole(ssoExchangeVo.getUserRole()); + authAccessVo.setUserType(ssoExchangeVo.getUserType()); - return ApiResponse.entity(result, ApiResponseCode.CODE_2001, "토큰"); + return ApiResponse.entity(authAccessVo, ApiResponseCode.CODE_2001, "토큰"); } @Operation( - summary = "리프레시 토큰으로 엑세스 토큰 재발급", - description = "리프레시 토큰으로 엑세스 토큰 재발급" + summary = "리프레시 토큰으로 엑세스 토큰 재발급" + , description = "리프레시 토큰으로 엑세스 토큰 재발급" ) @PostMapping("/refresh") - public ResponseEntity>> refresh( + public ResponseEntity> authRefresh( @CookieValue(name = "refreshToken", required = false) String refreshToken , HttpServletResponse response ) { + AuthRefreshVo authRefreshVo = authService.selectAuthRefresh(refreshToken); - LoginDto result = authService.refreshByToken(refreshToken); - - if (result == null) { - return ApiResponse.entity(Map.of("refreshed", false), ApiResponseCode.CODE_401); + if (authRefreshVo == null) { + AuthRefreshVo authRefreshVo1 = new AuthRefreshVo(); + authRefreshVo1.setRefreshed(false); + return ApiResponse.entity(authRefreshVo1, ApiResponseCode.CODE_401); } - SessionUtil.addTokenCookie(response, "accessToken", result.getAccessToken(), cookieDomain, cookieSecure, cookieSameSite, accessTokenValiditySeconds); - SessionUtil.addTokenCookie(response, "refreshToken", result.getRefreshToken(), cookieDomain, cookieSecure, cookieSameSite, refreshTokenValiditySeconds); + SessionUtil.addTokenCookie(response, "accessToken", authRefreshVo.getAccessToken(), cookieDomain, cookieSecure, cookieSameSite, accessTokenValiditySeconds); + SessionUtil.addTokenCookie(response, "refreshToken", authRefreshVo.getRefreshToken(), cookieDomain, cookieSecure, cookieSameSite, refreshTokenValiditySeconds); - return ApiResponse.entity(Map.of("refreshed", true), ApiResponseCode.CODE_200); + return ApiResponse.entity(authRefreshVo, ApiResponseCode.CODE_200); } @Operation( - summary = "API Key 로그인", - description = "API Key로 인증하고 JSON으로 토큰을 반환합니다. (OpenAPI/외부 서비스용)" + summary = "API Key 로그인" + , description = "API Key로 인증하고 JSON으로 토큰을 반환합니다. (OpenAPI/외부 서비스용)" ) @PostMapping("/apiKeyLogin") - public ResponseEntity> apiKeyLogin(@Valid @RequestBody ApikeyLoginForm apiKeyLoginForm) { - LoginDto result = authService.selectUserApiKeyLogin(apiKeyLoginForm.toLoginDto()); + public ResponseEntity> authApiKeyLogin(@Valid @RequestBody AuthApiKeyLoginForm authApiKeyLoginForm) { + AuthApiKeyLoginVo authApiKeyLoginVo = authService.selectAuthApiKeyLogin(authApiKeyLoginForm.toDto()); - if (result.getResultCode() == 2003) { - return ApiResponse.entity(result, ApiResponseCode.CODE_2003); + if (authApiKeyLoginVo.getResultCode() == 2003) { + return ApiResponse.entity(authApiKeyLoginVo, ApiResponseCode.CODE_2003); } - return ApiResponse.entity(result, ApiResponseCode.CODE_2001, "엑세스 토큰"); + return ApiResponse.entity(authApiKeyLoginVo, ApiResponseCode.CODE_2001, "엑세스 토큰"); } } diff --git a/src/main/java/com/alist/api/modules/auth/SsoController.java b/src/main/java/com/alist/api/modules/auth/SsoController.java index 50d6bbc..eac0165 100644 --- a/src/main/java/com/alist/api/modules/auth/SsoController.java +++ b/src/main/java/com/alist/api/modules/auth/SsoController.java @@ -3,13 +3,14 @@ package com.alist.api.modules.auth; import com.alist.api.common.response.ApiResponse; import com.alist.api.common.response.ApiResponseCode; import com.alist.api.common.utils.SessionUtil; -import com.alist.api.modules.auth.dto.SsoExchangeDto; -import com.alist.api.modules.auth.dto.SsoLoginCheckDto; -import com.alist.api.modules.auth.dto.SsoLoginDto; import com.alist.api.modules.auth.form.SsoExchangeForm; import com.alist.api.modules.auth.form.SsoLoginForm; -import com.alist.api.modules.auth.service.SsoService; import com.alist.api.modules.auth.service.AuthService; +import com.alist.api.modules.auth.service.SsoService; +import com.alist.api.modules.auth.vo.SsoExchangeVo; +import com.alist.api.modules.auth.vo.SsoLoginCheckedVo; +import com.alist.api.modules.auth.vo.SsoLoginVo; +import com.alist.api.modules.auth.vo.SsoLogoutVo; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; @@ -20,8 +21,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.net.URI; -import java.util.HashMap; -import java.util.Map; @Tag(name = "101. SSO 인증", description = "공통 로그인, 인가 코드 발급, 코드 교환, 로그아웃 관련 API") @RestController @@ -50,126 +49,124 @@ public class SsoController { } @Operation( - summary = "SSO 로그인", - description = "아이디/비밀번호로 공통 SSO 로그인 상태를 생성하고 HttpOnly 쿠키를 발급합니다." + summary = "SSO 로그인" + , description = "아이디/비밀번호로 공통 SSO 로그인 상태를 생성하고 HttpOnly 쿠키를 발급합니다." ) @PostMapping("/login") - public ResponseEntity> login( + public ResponseEntity> ssoLogin( @Valid @RequestBody SsoLoginForm ssoLoginForm - , HttpServletRequest request , HttpServletResponse response ) { - SsoLoginDto ssoLoginDto = ssoService.login(ssoLoginForm.toSsoLoginDto(), request); + SsoLoginVo ssoLoginVo = ssoService.selectSsoLogin(ssoLoginForm.toDto()); - SsoLoginCheckDto result = new SsoLoginCheckDto(); - - if (ssoLoginDto.getResultCode() == 2003) { - result.setLoginIn(false); - return ApiResponse.entity(result, ApiResponseCode.CODE_2003); + if (ssoLoginVo.getResultCode() == 2003) { + SsoLoginVo ssoLoginVo1 = new SsoLoginVo(); + ssoLoginVo1.setLoginIn(false); + return ApiResponse.entity(ssoLoginVo1, ApiResponseCode.CODE_2003); } - SessionUtil.addTokenCookie(response, ssoCookieName, ssoLoginDto.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite, ssoSessionTtlSeconds); + SessionUtil.addTokenCookie(response, ssoCookieName, ssoLoginVo.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite, ssoSessionTtlSeconds); - result.setLoginIn(true); - result.setId(ssoLoginDto.getUserId()); - result.setUserIdx(ssoLoginDto.getUserIdx()); - result.setUserRole(ssoLoginDto.getUserRole()); - result.setUserType(ssoLoginDto.getUserType()); + ssoLoginVo.setLoginIn(true); + ssoLoginVo.setId(ssoLoginVo.getUserId()); - return ApiResponse.entity(result, ApiResponseCode.CODE_2001, "SSO 로그인"); + return ApiResponse.entity(ssoLoginVo, ApiResponseCode.CODE_2001, "SSO 로그인"); } @Operation( - summary = "SSO 로그인 상태 확인", - description = "SSO 쿠키 기준으로 현재 공통 로그인 상태가 유효한지 확인하고, access/refresh 토큰 존재 여부도 함께 반환합니다." + summary = "SSO 로그인 상태 확인" + , description = "SSO 쿠키 기준으로 현재 공통 로그인 상태가 유효한지 확인하고, access/refresh 토큰 존재 여부도 함께 반환합니다." ) @GetMapping("/loginChecked") - public ResponseEntity>> loginChecked( + public ResponseEntity> ssoLoginChecked( HttpServletRequest request , HttpServletResponse response ) { String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName); - Map result = new HashMap<>(); + SsoLoginCheckedVo ssoLoginCheckedVo = new SsoLoginCheckedVo(); - SsoExchangeDto ssoSession = ssoService.loginChecked(ssoSessionId); + SsoExchangeVo ssoExchangeVo = ssoService.selectSsoLoginChecked(ssoSessionId); String accessToken = SessionUtil.resolveSsoCookieValue(request, "accessToken"); String refreshToken = SessionUtil.resolveSsoCookieValue(request, "refreshToken"); - result.put("isAccessToken", accessToken != null && !accessToken.trim().isEmpty()); - result.put("isRefreshToken", refreshToken != null && !refreshToken.trim().isEmpty()); + ssoLoginCheckedVo.setAccessToken(accessToken != null && !accessToken.trim().isEmpty()); + ssoLoginCheckedVo.setRefreshToken(refreshToken != null && !refreshToken.trim().isEmpty()); - if (ssoSession == null) { - result.put("loggedIn", false); - return ApiResponse.entity(result, ApiResponseCode.CODE_200); + if (ssoExchangeVo == null) { + ssoLoginCheckedVo.setLoggedIn(false); + return ApiResponse.entity(ssoLoginCheckedVo, ApiResponseCode.CODE_200); } - SessionUtil.addTokenCookie(response, ssoCookieName, ssoSession.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite,ssoSessionTtlSeconds); + SessionUtil.addTokenCookie(response, ssoCookieName, ssoExchangeVo.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite, ssoSessionTtlSeconds); - result.put("loggedIn", true); - result.put("ssoSessionId", ssoSession.getSsoSessionId()); - result.put("userId", ssoSession.getUserId()); - result.put("userIdx", ssoSession.getUserIdx()); - result.put("userTokenIdx", ssoSession.getUserTokenIdx()); - result.put("userRole", ssoSession.getUserRole()); - result.put("userType", ssoSession.getUserType()); + ssoLoginCheckedVo.setLoggedIn(true); + ssoLoginCheckedVo.setSsoSessionId(ssoExchangeVo.getSsoSessionId()); + ssoLoginCheckedVo.setUserId(ssoExchangeVo.getUserId()); + ssoLoginCheckedVo.setUserIdx(ssoExchangeVo.getUserIdx()); + ssoLoginCheckedVo.setUserTokenIdx(ssoExchangeVo.getUserTokenIdx()); + ssoLoginCheckedVo.setUserRole(ssoExchangeVo.getUserRole()); + ssoLoginCheckedVo.setUserType(ssoExchangeVo.getUserType()); - return ApiResponse.entity(result, ApiResponseCode.CODE_200); + return ApiResponse.entity(ssoLoginCheckedVo, ApiResponseCode.CODE_200); } @Operation( - summary = "SSO 인가 코드 발급", - description = "공통 로그인 상태를 확인한 뒤 대상 서비스로 이동할 1회용 인가 코드를 발급하고 redirectUri 로 리다이렉트합니다." + summary = "SSO 인가 코드 발급" + , description = "공통 로그인 상태를 확인한 뒤 대상 서비스로 이동할 1회용 인가 코드를 발급하고 redirectUri 로 리다이렉트합니다." ) @GetMapping("/authorize") - public ResponseEntity authorize( + public ResponseEntity ssoAuthorize( @RequestParam("clientId") String clientId , @RequestParam("redirectUri") String redirectUri , @RequestParam(value = "state", required = false) String state , HttpServletRequest request ) { String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName); - String redirectUrl = ssoService.authorize(clientId, redirectUri, state, ssoSessionId); + String redirectUrl = ssoService.selectSsoAuthorize(clientId, redirectUri, state, ssoSessionId); return ResponseEntity.status(302).location(URI.create(redirectUrl)).build(); } @Operation( - summary = "SSO 인가 코드 교환", - description = "서비스가 전달받은 1회용 인가 코드를 검증하고, 자체 세션 생성에 필요한 사용자 정보를 반환합니다." + summary = "SSO 인가 코드 교환" + , description = "서비스가 전달받은 1회용 인가 코드를 검증하고, 자체 세션 생성에 필요한 사용자 정보를 반환합니다." ) @PostMapping("/exchange") - public ResponseEntity> exchange( + public ResponseEntity> ssoExchange( @Valid @RequestBody SsoExchangeForm ssoExchangeForm , HttpServletResponse response ) { - SsoExchangeDto result = ssoService.exchange(ssoExchangeForm.toSsoExchangeDto()); + SsoExchangeVo ssoExchangeVo = ssoService.selectSsoExchange(ssoExchangeForm.toDto()); - SessionUtil.addTokenCookie(response, ssoCookieName, result.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite, ssoSessionTtlSeconds); + SessionUtil.addTokenCookie(response, ssoCookieName, ssoExchangeVo.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite, ssoSessionTtlSeconds); - return ApiResponse.entity(result, ApiResponseCode.CODE_2001, "SSO code 교환"); + return ApiResponse.entity(ssoExchangeVo, ApiResponseCode.CODE_2001, "SSO code 교환"); } @Operation( - summary = "SSO 로그아웃", - description = "공통 로그인 세션을 만료시켜 이후 authorize 및 서비스 접근 시 재로그인이 필요하도록 처리합니다." + summary = "SSO 로그아웃" + , description = "공통 로그인 세션을 만료시켜 이후 authorize 및 서비스 접근 시 재로그인이 필요하도록 처리합니다." ) @PostMapping("/logout") - public ResponseEntity>> logout( + public ResponseEntity> ssoLogout( HttpServletRequest request , HttpServletResponse response , @CookieValue(name = "refreshToken", required = false) String refreshToken ) { String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName); - ssoService.logout(ssoSessionId); + ssoService.updateSsoLogout(ssoSessionId); authService.clearRefreshToken(refreshToken); SessionUtil.expireCookie(response, ssoCookieName, cookieDomain, cookieSecure, cookieSameSite); SessionUtil.expireCookie(response, "accessToken", cookieDomain, cookieSecure, cookieSameSite); SessionUtil.expireCookie(response, "refreshToken", cookieDomain, cookieSecure, cookieSameSite); - return ApiResponse.entity(Map.of("logout", true), ApiResponseCode.CODE_200); + SsoLogoutVo ssoLogoutVo = new SsoLogoutVo(); + ssoLogoutVo.setLogout(true); + + return ApiResponse.entity(ssoLogoutVo, ApiResponseCode.CODE_200); } } diff --git a/src/main/java/com/alist/api/modules/auth/dto/AuthTokenDto.java b/src/main/java/com/alist/api/modules/auth/dto/AuthTokenDto.java new file mode 100644 index 0000000..518efbb --- /dev/null +++ b/src/main/java/com/alist/api/modules/auth/dto/AuthTokenDto.java @@ -0,0 +1,24 @@ +package com.alist.api.modules.auth.dto; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "테스트용 토큰 발급 요청 DTO") +@Getter +@Setter +public class AuthTokenDto { + @Schema(description = "아이디") + private String id; + + @Schema(description = "엑세스 토큰") + private String accessToken; + + @Schema(description = "리플레시 토큰") + private String refreshToken; + + @JsonIgnore + @Schema(hidden = true) + private int resultCode; +} diff --git a/src/main/java/com/alist/api/modules/auth/dto/SsoLoginDto.java b/src/main/java/com/alist/api/modules/auth/dto/SsoLoginDto.java index beb02e7..4ea4d6f 100644 --- a/src/main/java/com/alist/api/modules/auth/dto/SsoLoginDto.java +++ b/src/main/java/com/alist/api/modules/auth/dto/SsoLoginDto.java @@ -17,7 +17,7 @@ public class SsoLoginDto { private String userRole; private String userType; - public LoginDto toLoginDto() { + public LoginDto toDto() { LoginDto loginDto = new LoginDto(); loginDto.setId(this.id); loginDto.setPassword(this.password); diff --git a/src/main/java/com/alist/api/modules/auth/form/ApikeyLoginForm.java b/src/main/java/com/alist/api/modules/auth/form/AuthApiKeyLoginForm.java similarity index 60% rename from src/main/java/com/alist/api/modules/auth/form/ApikeyLoginForm.java rename to src/main/java/com/alist/api/modules/auth/form/AuthApiKeyLoginForm.java index 2968cc9..d5988eb 100644 --- a/src/main/java/com/alist/api/modules/auth/form/ApikeyLoginForm.java +++ b/src/main/java/com/alist/api/modules/auth/form/AuthApiKeyLoginForm.java @@ -9,18 +9,18 @@ import lombok.Setter; @Schema(description = "API Key 로그인 요청 폼") @Getter @Setter -public class ApikeyLoginForm { +public class AuthApiKeyLoginForm { @Schema( - description = "사용자 API Key", - example = "YjeWJr9-N-XaJ7ix2M2spnfjOyG9nTmRlY9t6sKw4_M", - requiredMode = Schema.RequiredMode.REQUIRED + description = "사용자 API Key" + , example = "YjeWJr9-N-XaJ7ix2M2spnfjOyG9nTmRlY9t6sKw4_M" + , requiredMode = Schema.RequiredMode.REQUIRED ) @NotBlank(message = "apiKey를 입력해주세요.") private String userApiKey; - public LoginDto toLoginDto() { + public LoginDto toDto() { LoginDto loginDto = new LoginDto(); - loginDto.setUserApiKey(this.userApiKey.trim()); + loginDto.setUserApiKey(userApiKey == null ? null : userApiKey.trim()); return loginDto; } diff --git a/src/main/java/com/alist/api/modules/auth/form/AuthTokenForm.java b/src/main/java/com/alist/api/modules/auth/form/AuthTokenForm.java new file mode 100644 index 0000000..96c549b --- /dev/null +++ b/src/main/java/com/alist/api/modules/auth/form/AuthTokenForm.java @@ -0,0 +1,24 @@ +package com.alist.api.modules.auth.form; + +import com.alist.api.modules.auth.dto.AuthTokenDto; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Schema(description = "토큰 요청 폼") +public class AuthTokenForm { + + @NotBlank(message = "사용자명은 필수입니다.") + @Schema(description = "사용자명", example = "test") + private String id; + + public AuthTokenDto toDto() { + AuthTokenDto authTokenDto = new AuthTokenDto(); + authTokenDto.setId(this.id.trim()); + + return authTokenDto; + } +} \ No newline at end of file diff --git a/src/main/java/com/alist/api/modules/auth/form/SsoExchangeForm.java b/src/main/java/com/alist/api/modules/auth/form/SsoExchangeForm.java index c2af113..8a42a55 100644 --- a/src/main/java/com/alist/api/modules/auth/form/SsoExchangeForm.java +++ b/src/main/java/com/alist/api/modules/auth/form/SsoExchangeForm.java @@ -11,22 +11,22 @@ import lombok.Setter; @Setter public class SsoExchangeForm { @Schema( - description = "SSO 인가 코드", - example = "authorization-code", - requiredMode = Schema.RequiredMode.REQUIRED + description = "SSO 인가 코드" + , example = "authorization-code" + , requiredMode = Schema.RequiredMode.REQUIRED ) @NotBlank(message = "인가 코드는 필수입니다.") private String code; @Schema( - description = "SSO 클라이언트 ID", - example = "alist-main", - requiredMode = Schema.RequiredMode.REQUIRED + description = "SSO 클라이언트 ID" + , example = "alist-main" + , requiredMode = Schema.RequiredMode.REQUIRED ) @NotBlank(message = "클라이언트 ID는 필수입니다.") private String clientId; - public SsoExchangeDto toSsoExchangeDto() { + public SsoExchangeDto toDto() { SsoExchangeDto ssoExchangeDto = new SsoExchangeDto(); ssoExchangeDto.setCode(code == null ? null : code.trim()); ssoExchangeDto.setClientId(clientId == null ? null : clientId.trim()); diff --git a/src/main/java/com/alist/api/modules/auth/form/SsoLoginForm.java b/src/main/java/com/alist/api/modules/auth/form/SsoLoginForm.java index 26609ed..71121ce 100644 --- a/src/main/java/com/alist/api/modules/auth/form/SsoLoginForm.java +++ b/src/main/java/com/alist/api/modules/auth/form/SsoLoginForm.java @@ -11,22 +11,22 @@ import lombok.Setter; @Setter public class SsoLoginForm { @Schema( - description = "회원 아이디", - example = "test", - requiredMode = Schema.RequiredMode.REQUIRED + description = "회원 아이디" + , example = "test" + , requiredMode = Schema.RequiredMode.REQUIRED ) @NotBlank(message = "아이디는 필수입니다.") private String id; @Schema( - description = "비밀번호", - example = "password1234", - requiredMode = Schema.RequiredMode.REQUIRED + description = "비밀번호" + , example = "password1234" + , requiredMode = Schema.RequiredMode.REQUIRED ) @NotBlank(message = "비밀번호는 필수입니다.") private String password; - public SsoLoginDto toSsoLoginDto() { + public SsoLoginDto toDto() { SsoLoginDto ssoLoginDto = new SsoLoginDto(); ssoLoginDto.setId(id == null ? null : id.trim()); ssoLoginDto.setPassword(password == null ? null : password.trim()); diff --git a/src/main/java/com/alist/api/modules/auth/form/TokenForm.java b/src/main/java/com/alist/api/modules/auth/form/TokenForm.java deleted file mode 100644 index aed3c0b..0000000 --- a/src/main/java/com/alist/api/modules/auth/form/TokenForm.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.alist.api.modules.auth.form; - -import com.alist.api.modules.auth.dto.TokenDto; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@Schema(description = "토큰 요청 폼") -public class TokenForm { - - @NotBlank(message = "사용자명은 필수입니다.") - @Schema(description = "사용자명", example = "test") - private String id; - - public TokenDto toTokenDto() { - TokenDto tokenDto = new TokenDto(); - tokenDto.setId(this.id.trim()); - - return tokenDto; - } -} \ No newline at end of file diff --git a/src/main/java/com/alist/api/modules/auth/mapper/AuthMapper.java b/src/main/java/com/alist/api/modules/auth/mapper/AuthMapper.java index 4d305ee..d16fb1a 100644 --- a/src/main/java/com/alist/api/modules/auth/mapper/AuthMapper.java +++ b/src/main/java/com/alist/api/modules/auth/mapper/AuthMapper.java @@ -4,7 +4,6 @@ import com.alist.api.modules.auth.dto.LoginDto; import com.alist.api.modules.auth.vo.LoginTokenVo; import com.alist.api.modules.auth.vo.LoginVo; import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; @Mapper public interface AuthMapper { @@ -20,5 +19,5 @@ public interface AuthMapper { void clearRefreshTokenByUserTokenIdx(int userTokenIdx); - void updateLoginByLastAt(LoginDto loginDto); + void updateLoginByLastAt(LoginDto loginDto); } diff --git a/src/main/java/com/alist/api/modules/auth/service/AuthService.java b/src/main/java/com/alist/api/modules/auth/service/AuthService.java index 1ff1678..041d341 100644 --- a/src/main/java/com/alist/api/modules/auth/service/AuthService.java +++ b/src/main/java/com/alist/api/modules/auth/service/AuthService.java @@ -4,6 +4,8 @@ import com.alist.api.config.jwt.JwtTokenProvider; import com.alist.api.config.properties.JwtProperties; import com.alist.api.modules.auth.dto.LoginDto; import com.alist.api.modules.auth.mapper.AuthMapper; +import com.alist.api.modules.auth.vo.AuthApiKeyLoginVo; +import com.alist.api.modules.auth.vo.AuthRefreshVo; import com.alist.api.modules.auth.vo.LoginTokenVo; import com.alist.api.modules.auth.vo.LoginVo; import lombok.extern.slf4j.Slf4j; @@ -28,70 +30,88 @@ public class AuthService { this.jwtProperties = jwtProperties; } - // id login - public LoginDto selectLogin(LoginDto loginDto) { + @Transactional + public LoginVo selectLogin(LoginDto loginDto) { LoginVo loginVo = authMapper.selectLogin(loginDto); - if (loginVo != null) { - if (passwordEncoder.matches(loginDto.getPassword(), loginVo.getPassword())) { - - loginDto.setUserIdx(loginVo.getUserIdx()); - - LoginTokenVo loginTokenVo = authMapper.selectUserTokenByUserId(loginDto); - - if (loginTokenVo != null) { - loginDto.setAccessToken(jwtTokenProvider.createAccessToken(loginTokenVo.getUserTokenIdx(), loginTokenVo.getUserRole())); - loginDto.setRefreshToken(jwtTokenProvider.createRefreshToken(loginTokenVo.getUserTokenIdx())); - - loginDto.setUserTokenIdx(loginTokenVo.getUserTokenIdx()); - loginDto.setUserRole(loginTokenVo.getUserRole()); - loginDto.setUserType(loginTokenVo.getUserType()); - - Instant now = Instant.now(); - Instant expiresAt = now.plusSeconds(jwtProperties.getRefreshTokenValiditySeconds()); - - loginDto.setExpiresAt(expiresAt); - - authMapper.updateRefreshToken(loginDto); - - // 마지막 로그인 시간 추가 - authMapper.updateLoginByLastAt(loginDto); - - loginDto.setResultCode(2001); - } else { - loginDto.setResultCode(2003); - } - } else { - loginDto.setResultCode(2003); - } - } else { - loginDto.setResultCode(2003); + if (loginVo == null) { + LoginVo loginVo1 = new LoginVo(); + loginVo1.setResultCode(2003); + return loginVo1; } - return loginDto; - } - - // api key login - public LoginDto selectUserApiKeyLogin(LoginDto loginDto) { - if (loginDto.getUserApiKey() != null) { - LoginTokenVo loginTokenVo = authMapper.selectUserTokenByUserApiKey(loginDto); - - if (loginTokenVo != null) { - loginDto.setAccessToken(jwtTokenProvider.createAccessToken(loginTokenVo.getUserTokenIdx(), loginTokenVo.getUserRole())); - loginDto.setRefreshToken(jwtTokenProvider.createRefreshToken(loginTokenVo.getUserTokenIdx())); - - loginDto.setResultCode(2001); - } else { - loginDto.setResultCode(2003); - } - } else { - loginDto.setResultCode(2003); + if (!passwordEncoder.matches(loginDto.getPassword(), loginVo.getPassword())) { + LoginVo loginVo1 = new LoginVo(); + loginVo1.setResultCode(2003); + return loginVo1; } - return loginDto; + loginDto.setUserIdx(loginVo.getUserIdx()); + LoginTokenVo loginTokenVo = authMapper.selectUserTokenByUserId(loginDto); + + if (loginTokenVo == null) { + LoginVo loginVo1 = new LoginVo(); + loginVo1.setResultCode(2003); + return loginVo1; + } + + String accessToken = jwtTokenProvider.createAccessToken(loginTokenVo.getUserTokenIdx(), loginTokenVo.getUserRole()); + String refreshToken = jwtTokenProvider.createRefreshToken(loginTokenVo.getUserTokenIdx()); + + Instant expiresAt = Instant.now().plusSeconds(jwtProperties.getRefreshTokenValiditySeconds()); + + loginVo.setAccessToken(accessToken); + loginVo.setRefreshToken(refreshToken); + loginVo.setUserTokenIdx(loginTokenVo.getUserTokenIdx()); + loginVo.setUserRole(loginTokenVo.getUserRole()); + loginVo.setUserType(loginTokenVo.getUserType()); + loginVo.setExpiresAt(expiresAt); + loginVo.setResultCode(2001); + + loginDto.setUserTokenIdx(loginVo.getUserTokenIdx()); + loginDto.setRefreshToken(loginVo.getRefreshToken()); + loginDto.setExpiresAt(loginVo.getExpiresAt()); + + authMapper.updateRefreshToken(loginDto); + authMapper.updateLoginByLastAt(loginDto); + + return loginVo; } - public LoginDto refreshByToken(String refreshToken) { + @Transactional + public AuthApiKeyLoginVo selectAuthApiKeyLogin(LoginDto loginDto) { + AuthApiKeyLoginVo authApiKeyLoginVo = new AuthApiKeyLoginVo(); + + if (loginDto.getUserApiKey() == null) { + authApiKeyLoginVo.setResultCode(2003); + return authApiKeyLoginVo; + } + + LoginTokenVo loginTokenVo = authMapper.selectUserTokenByUserApiKey(loginDto); + + if (loginTokenVo == null) { + authApiKeyLoginVo.setResultCode(2003); + return authApiKeyLoginVo; + } + + String accessToken = jwtTokenProvider.createAccessToken(loginTokenVo.getUserTokenIdx(), loginTokenVo.getUserRole()); + String refreshToken = jwtTokenProvider.createRefreshToken(loginTokenVo.getUserTokenIdx()); + + loginDto.setUserTokenIdx(loginTokenVo.getUserTokenIdx()); + loginDto.setRefreshToken(refreshToken); + loginDto.setExpiresAt(Instant.now().plusSeconds(jwtProperties.getRefreshTokenValiditySeconds())); + + authMapper.updateRefreshToken(loginDto); + + authApiKeyLoginVo.setAccessToken(accessToken); + authApiKeyLoginVo.setRefreshToken(refreshToken); + authApiKeyLoginVo.setResultCode(2001); + + return authApiKeyLoginVo; + } + + @Transactional + public AuthRefreshVo selectAuthRefresh(String refreshToken) { if (refreshToken == null || !jwtTokenProvider.validateToken(refreshToken)) { return null; } @@ -112,14 +132,22 @@ public class AuthService { return null; } - LoginDto result = new LoginDto(); - result.setUserTokenIdx(userTokenIdx); - result.setAccessToken(jwtTokenProvider.createAccessToken(tokenVo.getUserTokenIdx(), tokenVo.getUserRole())); - result.setRefreshToken(jwtTokenProvider.createRefreshToken(tokenVo.getUserTokenIdx())); - result.setExpiresAt(Instant.now().plusSeconds(jwtProperties.getRefreshTokenValiditySeconds())); + String newAccessToken = jwtTokenProvider.createAccessToken(tokenVo.getUserTokenIdx(), tokenVo.getUserRole()); + String newRefreshToken = jwtTokenProvider.createRefreshToken(tokenVo.getUserTokenIdx()); - authMapper.updateRefreshToken(result); - return result; + LoginDto loginDto = new LoginDto(); + loginDto.setUserTokenIdx(userTokenIdx); + loginDto.setRefreshToken(newRefreshToken); + loginDto.setExpiresAt(Instant.now().plusSeconds(jwtProperties.getRefreshTokenValiditySeconds())); + + authMapper.updateRefreshToken(loginDto); + + AuthRefreshVo authRefreshVo = new AuthRefreshVo(); + authRefreshVo.setAccessToken(newAccessToken); + authRefreshVo.setRefreshToken(newRefreshToken); + authRefreshVo.setRefreshed(true); + + return authRefreshVo; } public void clearRefreshToken(String refreshToken) { diff --git a/src/main/java/com/alist/api/modules/auth/service/SsoService.java b/src/main/java/com/alist/api/modules/auth/service/SsoService.java index b3a3a4b..b1511b4 100644 --- a/src/main/java/com/alist/api/modules/auth/service/SsoService.java +++ b/src/main/java/com/alist/api/modules/auth/service/SsoService.java @@ -2,10 +2,11 @@ package com.alist.api.modules.auth.service; import com.alist.api.modules.auth.dto.SsoExchangeDto; import com.alist.api.modules.auth.dto.SsoLoginDto; -import com.alist.api.modules.auth.dto.LoginDto; import com.alist.api.modules.auth.mapper.SsoMapper; +import com.alist.api.modules.auth.vo.LoginVo; import com.alist.api.modules.auth.vo.SsoClientVo; -import jakarta.servlet.http.HttpServletRequest; +import com.alist.api.modules.auth.vo.SsoExchangeVo; +import com.alist.api.modules.auth.vo.SsoLoginVo; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; @@ -32,18 +33,18 @@ public class SsoService { this.ssoCodeTtl = Duration.ofSeconds(ssoCodeTtlSeconds); } - public SsoLoginDto login(SsoLoginDto ssoLoginDto, HttpServletRequest request) { - LoginDto loginDto = authService.selectLogin(ssoLoginDto.toLoginDto()); + public SsoLoginVo selectSsoLogin(SsoLoginDto ssoLoginDto) { + LoginVo loginVo = authService.selectLogin(ssoLoginDto.toDto()); - SsoLoginDto result = new SsoLoginDto(); - result.setResultCode(loginDto.getResultCode()); + SsoLoginVo ssoLoginVo = new SsoLoginVo(); + ssoLoginVo.setResultCode(loginVo.getResultCode()); - if (loginDto.getResultCode() == 2003) { - return result; + if (loginVo.getResultCode() == 2003) { + return ssoLoginVo; } String ssoSessionId = "SSO_" + UUID.randomUUID(); - String latestSessionKey = "alist:sso:userIdx:" + loginDto.getUserIdx(); + String latestSessionKey = "alist:sso:userIdx:" + loginVo.getUserIdx(); String sessionKey = "alist:sso:session:" + ssoSessionId; String oldSsoSessionId = redisTemplate.opsForValue().get(latestSessionKey); @@ -51,26 +52,26 @@ public class SsoService { redisTemplate.delete("alist:sso:session:" + oldSsoSessionId); } - redisTemplate.opsForHash().put(sessionKey, "userIdx", String.valueOf(loginDto.getUserIdx())); - redisTemplate.opsForHash().put(sessionKey, "userTokenIdx", String.valueOf(loginDto.getUserTokenIdx())); - redisTemplate.opsForHash().put(sessionKey, "userId", loginDto.getId()); - redisTemplate.opsForHash().put(sessionKey, "userRole", loginDto.getUserRole()); - redisTemplate.opsForHash().put(sessionKey, "userType", loginDto.getUserType()); + redisTemplate.opsForHash().put(sessionKey, "userIdx", String.valueOf(loginVo.getUserIdx())); + redisTemplate.opsForHash().put(sessionKey, "userTokenIdx", String.valueOf(loginVo.getUserTokenIdx())); + redisTemplate.opsForHash().put(sessionKey, "userId", loginVo.getId()); + redisTemplate.opsForHash().put(sessionKey, "userRole", loginVo.getUserRole()); + redisTemplate.opsForHash().put(sessionKey, "userType", loginVo.getUserType()); redisTemplate.expire(sessionKey, ssoSessionTtl); redisTemplate.opsForValue().set(latestSessionKey, ssoSessionId, ssoSessionTtl); - result.setSsoSessionId(ssoSessionId); - result.setUserId(loginDto.getId()); - result.setUserIdx(loginDto.getUserIdx()); - result.setUserRole(loginDto.getUserRole()); - result.setUserType(loginDto.getUserType()); - result.setResultCode(200); + ssoLoginVo.setSsoSessionId(ssoSessionId); + ssoLoginVo.setUserId(loginVo.getId()); + ssoLoginVo.setUserIdx(loginVo.getUserIdx()); + ssoLoginVo.setUserRole(loginVo.getUserRole()); + ssoLoginVo.setUserType(loginVo.getUserType()); + ssoLoginVo.setResultCode(200); - return result; + return ssoLoginVo; } - public SsoExchangeDto loginChecked(String ssoSessionId) { + public SsoExchangeVo selectSsoLoginChecked(String ssoSessionId) { if (ssoSessionId == null || ssoSessionId.isBlank()) { return null; } @@ -94,18 +95,18 @@ public class SsoService { String userRole = (String) redisTemplate.opsForHash().get(sessionKey, "userRole"); String userType = (String) redisTemplate.opsForHash().get(sessionKey, "userType"); - SsoExchangeDto result = new SsoExchangeDto(); - result.setSsoSessionId(ssoSessionId); - result.setUserId(userId); - result.setUserIdx(userIdx == null ? null : Integer.parseInt(userIdx)); - result.setUserTokenIdx(userTokenIdx == null ? null : Integer.parseInt(userTokenIdx)); - result.setUserRole(userRole); - result.setUserType(userType); + SsoExchangeVo ssoExchangeVo = new SsoExchangeVo(); + ssoExchangeVo.setSsoSessionId(ssoSessionId); + ssoExchangeVo.setUserId(userId); + ssoExchangeVo.setUserIdx(userIdx == null ? null : Integer.parseInt(userIdx)); + ssoExchangeVo.setUserTokenIdx(userTokenIdx == null ? null : Integer.parseInt(userTokenIdx)); + ssoExchangeVo.setUserRole(userRole); + ssoExchangeVo.setUserType(userType); - return result; + return ssoExchangeVo; } - public String authorize(String clientId, String redirectUri, String state, String ssoSessionId) { + public String selectSsoAuthorize(String clientId, String redirectUri, String state, String ssoSessionId) { if (ssoSessionId == null || ssoSessionId.isBlank()) { return "/login"; } @@ -158,7 +159,7 @@ public class SsoService { return redirect.toString(); } - public SsoExchangeDto exchange(SsoExchangeDto ssoExchangeDto) { + public SsoExchangeVo selectSsoExchange(SsoExchangeDto ssoExchangeDto) { String codeKey = "alist:sso:code:" + ssoExchangeDto.getCode(); String ssoSessionId = (String) redisTemplate.opsForHash().get(codeKey, "ssoSessionId"); String clientId = (String) redisTemplate.opsForHash().get(codeKey, "clientId"); @@ -182,17 +183,18 @@ public class SsoService { refreshSsoSessionTtl(ssoSessionId, userIdx); redisTemplate.delete(codeKey); - SsoExchangeDto result = new SsoExchangeDto(); - result.setUserId(userId); - result.setUserIdx(Integer.parseInt(userIdx)); - result.setUserTokenIdx(Integer.parseInt(userTokenIdx)); - result.setUserRole(userRole); - result.setUserType(userType); - result.setSsoSessionId(ssoSessionId); - return result; + SsoExchangeVo ssoExchangeVo = new SsoExchangeVo(); + ssoExchangeVo.setUserId(userId); + ssoExchangeVo.setUserIdx(Integer.parseInt(userIdx)); + ssoExchangeVo.setUserTokenIdx(Integer.parseInt(userTokenIdx)); + ssoExchangeVo.setUserRole(userRole); + ssoExchangeVo.setUserType(userType); + ssoExchangeVo.setSsoSessionId(ssoSessionId); + + return ssoExchangeVo; } - public void logout(String ssoSessionId) { + public void updateSsoLogout(String ssoSessionId) { if (ssoSessionId == null || ssoSessionId.isBlank()) { return; } diff --git a/src/main/java/com/alist/api/modules/auth/vo/AuthAccessVo.java b/src/main/java/com/alist/api/modules/auth/vo/AuthAccessVo.java new file mode 100644 index 0000000..2b7bc47 --- /dev/null +++ b/src/main/java/com/alist/api/modules/auth/vo/AuthAccessVo.java @@ -0,0 +1,27 @@ +package com.alist.api.modules.auth.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "SSO 기반 토큰 발급 응답") +@Getter +@Setter +public class AuthAccessVo { + @JsonProperty("isAccessToken") + @Schema(description = "Access Token 발급 여부", example = "true") + private boolean accessToken; + + @Schema(description = "회원 PK", example = "1") + private Integer userIdx; + + @Schema(description = "회원 아이디", example = "test") + private String userId; + + @Schema(description = "회원 권한 코드", example = "CCD/SCM/I/R/E") + private String userRole; + + @Schema(description = "회원 유형 코드. T: 교사, S: 학생", example = "S") + private String userType; +} diff --git a/src/main/java/com/alist/api/modules/auth/vo/AuthApiKeyLoginVo.java b/src/main/java/com/alist/api/modules/auth/vo/AuthApiKeyLoginVo.java new file mode 100644 index 0000000..87ed9ad --- /dev/null +++ b/src/main/java/com/alist/api/modules/auth/vo/AuthApiKeyLoginVo.java @@ -0,0 +1,24 @@ +package com.alist.api.modules.auth.vo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "API Key 로그인 응답") +@Getter +@Setter +public class AuthApiKeyLoginVo { + @Schema(description = "아이디") + private String id; + + @Schema(description = "엑세스 토큰") + private String accessToken; + + @Schema(description = "리플레시 토큰") + private String refreshToken; + + @JsonIgnore + @Schema(hidden = true) + private int resultCode; +} diff --git a/src/main/java/com/alist/api/modules/auth/vo/AuthRefreshVo.java b/src/main/java/com/alist/api/modules/auth/vo/AuthRefreshVo.java new file mode 100644 index 0000000..e1354c2 --- /dev/null +++ b/src/main/java/com/alist/api/modules/auth/vo/AuthRefreshVo.java @@ -0,0 +1,22 @@ +package com.alist.api.modules.auth.vo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "Access Token 재발급 응답") +@Getter +@Setter +public class AuthRefreshVo { + @Schema(description = "토큰 재발급 여부", example = "true") + private boolean refreshed; + + @JsonIgnore + @Schema(hidden = true) + private String accessToken; + + @JsonIgnore + @Schema(hidden = true) + private String refreshToken; +} diff --git a/src/main/java/com/alist/api/modules/auth/dto/TokenDto.java b/src/main/java/com/alist/api/modules/auth/vo/AuthTokenVo.java similarity index 84% rename from src/main/java/com/alist/api/modules/auth/dto/TokenDto.java rename to src/main/java/com/alist/api/modules/auth/vo/AuthTokenVo.java index b278606..7092f08 100644 --- a/src/main/java/com/alist/api/modules/auth/dto/TokenDto.java +++ b/src/main/java/com/alist/api/modules/auth/vo/AuthTokenVo.java @@ -1,20 +1,20 @@ -package com.alist.api.modules.auth.dto; +package com.alist.api.modules.auth.vo; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; -import java.time.Instant; - @Schema(description = "테스트용 토큰 발급 응답") @Getter @Setter -public class TokenDto { +public class AuthTokenVo { @Schema(description = "아이디") private String id; + @Schema(description = "엑세스 토큰") private String accessToken; + @Schema(description = "리플레시 토큰") private String refreshToken; diff --git a/src/main/java/com/alist/api/modules/auth/vo/LoginVo.java b/src/main/java/com/alist/api/modules/auth/vo/LoginVo.java index 6c1340c..a4cf839 100644 --- a/src/main/java/com/alist/api/modules/auth/vo/LoginVo.java +++ b/src/main/java/com/alist/api/modules/auth/vo/LoginVo.java @@ -1,10 +1,22 @@ package com.alist.api.modules.auth.vo; import lombok.Getter; +import lombok.Setter; + +import java.time.Instant; @Getter +@Setter public class LoginVo { private Integer userIdx; private String id; private String password; + + private String accessToken; + private String refreshToken; + private Integer userTokenIdx; + private String userRole; + private String userType; + private Instant expiresAt; + private int resultCode; } diff --git a/src/main/java/com/alist/api/modules/auth/vo/SsoExchangeVo.java b/src/main/java/com/alist/api/modules/auth/vo/SsoExchangeVo.java new file mode 100644 index 0000000..cf4043e --- /dev/null +++ b/src/main/java/com/alist/api/modules/auth/vo/SsoExchangeVo.java @@ -0,0 +1,34 @@ +package com.alist.api.modules.auth.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "SSO 인가 코드 교환 응답") +@Getter +@Setter +public class SsoExchangeVo { + @Schema(description = "SSO 인가 코드", example = "authorization-code") + private String code; + + @Schema(description = "SSO 클라이언트 ID", example = "alist-main") + private String clientId; + + @Schema(description = "SSO 세션 ID") + private String ssoSessionId; + + @Schema(description = "회원 PK", example = "1") + private Integer userIdx; + + @Schema(description = "회원 토큰 PK", example = "1") + private Integer userTokenIdx; + + @Schema(description = "회원 아이디", example = "test") + private String userId; + + @Schema(description = "회원 권한 코드(CCD/SCM/I/R/E)", example = "SCM") + private String userRole; + + @Schema(description = "회원 유형 코드. T: 교사, S: 학생", example = "T") + private String userType; +} diff --git a/src/main/java/com/alist/api/modules/auth/vo/SsoLoginCheckedVo.java b/src/main/java/com/alist/api/modules/auth/vo/SsoLoginCheckedVo.java new file mode 100644 index 0000000..1649cff --- /dev/null +++ b/src/main/java/com/alist/api/modules/auth/vo/SsoLoginCheckedVo.java @@ -0,0 +1,40 @@ +package com.alist.api.modules.auth.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "SSO 로그인 상태 확인 응답") +@Getter +@Setter +public class SsoLoginCheckedVo { + @JsonProperty("isAccessToken") + @Schema(description = "Access Token 쿠키 존재 여부", example = "true") + private boolean accessToken; + + @JsonProperty("isRefreshToken") + @Schema(description = "Refresh Token 쿠키 존재 여부", example = "true") + private boolean refreshToken; + + @Schema(description = "로그인 상태 여부", example = "true") + private boolean loggedIn; + + @Schema(description = "SSO 세션 ID") + private String ssoSessionId; + + @Schema(description = "회원 아이디", example = "test") + private String userId; + + @Schema(description = "회원 PK", example = "1") + private Integer userIdx; + + @Schema(description = "회원 토큰 PK", example = "1") + private Integer userTokenIdx; + + @Schema(description = "회원 권한 코드", example = "CCD/SCM/I/R/E") + private String userRole; + + @Schema(description = "회원 유형 코드. T: 교사, S: 학생", example = "S") + private String userType; +} diff --git a/src/main/java/com/alist/api/modules/auth/dto/SsoLoginCheckDto.java b/src/main/java/com/alist/api/modules/auth/vo/SsoLoginVo.java similarity index 62% rename from src/main/java/com/alist/api/modules/auth/dto/SsoLoginCheckDto.java rename to src/main/java/com/alist/api/modules/auth/vo/SsoLoginVo.java index 7dd5002..6010b1d 100644 --- a/src/main/java/com/alist/api/modules/auth/dto/SsoLoginCheckDto.java +++ b/src/main/java/com/alist/api/modules/auth/vo/SsoLoginVo.java @@ -1,5 +1,6 @@ -package com.alist.api.modules.auth.dto; +package com.alist.api.modules.auth.vo; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; @@ -7,7 +8,7 @@ import lombok.Setter; @Schema(description = "SSO 로그인 응답") @Getter @Setter -public class SsoLoginCheckDto { +public class SsoLoginVo { @Schema(description = "로그인 성공 여부", example = "true") private boolean loginIn; @@ -22,4 +23,20 @@ public class SsoLoginCheckDto { @Schema(description = "회원 유형 코드. T: 교사, S: 학생", example = "S") private String userType; + + @JsonIgnore + @Schema(hidden = true) + private String ssoSessionId; + + @JsonIgnore + @Schema(hidden = true) + private Integer userTokenIdx; + + @JsonIgnore + @Schema(hidden = true) + private String userId; + + @JsonIgnore + @Schema(hidden = true) + private int resultCode; } diff --git a/src/main/java/com/alist/api/modules/auth/vo/SsoLogoutVo.java b/src/main/java/com/alist/api/modules/auth/vo/SsoLogoutVo.java new file mode 100644 index 0000000..271d722 --- /dev/null +++ b/src/main/java/com/alist/api/modules/auth/vo/SsoLogoutVo.java @@ -0,0 +1,13 @@ +package com.alist.api.modules.auth.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "SSO 로그아웃 응답") +@Getter +@Setter +public class SsoLogoutVo { + @Schema(description = "로그아웃 처리 여부", example = "true") + private boolean logout; +} diff --git a/src/main/java/com/alist/api/modules/auth/vo/TokenVo.java b/src/main/java/com/alist/api/modules/auth/vo/TokenVo.java deleted file mode 100644 index c44128e..0000000 --- a/src/main/java/com/alist/api/modules/auth/vo/TokenVo.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.alist.api.modules.auth.vo; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; -import lombok.Setter; - -@Schema(description = "테스트용 토큰 발급 응답") -@Getter -@Setter -public class TokenVo { - @Schema(description = "아이디") - private String id; - @Schema(description = "엑세스 토큰") - private String accessToken; - @Schema(description = "리플레시 토큰") - private String refreshToken; - - @JsonIgnore - @Schema(hidden = true) - private int resultCode; -} diff --git a/src/main/resources/mapper/auth/LoginMapper.xml b/src/main/resources/mapper/auth/LoginMapper.xml index 10d95a0..fd7eff1 100644 --- a/src/main/resources/mapper/auth/LoginMapper.xml +++ b/src/main/resources/mapper/auth/LoginMapper.xml @@ -67,7 +67,7 @@ /*LoginMapper.updateLoginByLastAt*/ update ALISTLMS.test_user set last_login_at = now() - , update_at = now() + , update_at = now() where user_idx = #{userIdx}