-
Notifications
You must be signed in to change notification settings - Fork 0
20260112 #5 로그인 및 기타 인증 관련 로직 개발 #7
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
Merged
The head ref may contain hidden characters: "20260112_#5_\uB85C\uADF8\uC778_\uBC0F_\uAE30\uD0C0_\uC778\uC99D_\uAD00\uB828_\uB85C\uC9C1_\uAC1C\uBC1C"
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
7fc59e8
로그인_및_기타_인증_관련_로직_개발 : feat : member 엔티티 학번: student_number 변경 https:…
Chuseok22 bff02e5
로그인_및_기타_인증_관련_로직_개발 : feat : member 엔티티 학번: student_number 변경 https:…
Chuseok22 b957750
로그인_및_기타_인증_관련_로직_개발 : feat : member 엔티티 학번: student_number 변경 https:…
Chuseok22 2b774f8
로그인_및_기타_인증_관련_로직_개발 : feat : 로그인 로직 추가 https://github.com/CampusTabl…
Chuseok22 baf8e13
로그인_및_기타_인증_관련_로직_개발 : feat : 로그인 컨트롤러 추가 https://github.com/CampusTa…
Chuseok22 43e886c
로그인_및_기타_인증_관련_로직_개발 : feat : 지역변수 재사용 https://github.com/CampusTable…
Chuseok22 4c7feb9
로그인_및_기타_인증_관련_로직_개발 : feat : LoginRequest.kt validation 적용 https://g…
Chuseok22 6d0f759
로그인_및_기타_인증_관련_로직_개발 : feat : JWT 저장 및 삭제를 위한 TokenManager.kt 추가 http…
Chuseok22 ec8378b
로그인_및_기타_인증_관련_로직_개발 : feat : Reissue & 로그아웃 로직 추가 https://github.com…
Chuseok22 e21b082
로그인_및_기타_인증_관련_로직_개발 : feat : Reissue & 로그아웃 컨트롤러 추가 https://github.c…
Chuseok22 37e543c
로그인_및_기타_인증_관련_로직_개발 : feat : 저장된 리프레시 토큰 검증 로직 추가 https://github.com…
Chuseok22 7af97fa
로그인_및_기타_인증_관련_로직_개발 : feat : spring validate 및 requestBody 어노테이션 추가 …
Chuseok22 b214dd0
로그인_및_기타_인증_관련_로직_개발 : feat : 리프레시 토큰을 통한 reissue 과정 검증 강화 https://gi…
Chuseok22 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
10 changes: 10 additions & 0 deletions
10
CT-auth/src/main/kotlin/com/chuseok22/ctauth/application/dto/request/LoginRequest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package com.chuseok22.ctauth.application.dto.request | ||
|
|
||
| import jakarta.validation.constraints.NotBlank | ||
|
|
||
| data class LoginRequest( | ||
| @field:NotBlank | ||
| val sejongPortalId: String, | ||
| @field:NotBlank | ||
| val sejongPortalPw: String | ||
| ) |
8 changes: 8 additions & 0 deletions
8
CT-auth/src/main/kotlin/com/chuseok22/ctauth/application/dto/request/ReissueRequest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package com.chuseok22.ctauth.application.dto.request | ||
|
|
||
| import jakarta.validation.constraints.NotBlank | ||
|
|
||
| data class ReissueRequest( | ||
| @field:NotBlank | ||
| val refreshToken: String | ||
| ) |
8 changes: 8 additions & 0 deletions
8
CT-auth/src/main/kotlin/com/chuseok22/ctauth/application/dto/response/LoginResponse.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package com.chuseok22.ctauth.application.dto.response | ||
|
|
||
| data class LoginResponse( | ||
| val studentNumber: String, | ||
| val name: String, | ||
| val accessToken: String, | ||
| val refreshToken: String | ||
| ) |
6 changes: 6 additions & 0 deletions
6
CT-auth/src/main/kotlin/com/chuseok22/ctauth/application/dto/response/ReissueResponse.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package com.chuseok22.ctauth.application.dto.response | ||
|
|
||
| data class ReissueResponse( | ||
| val accessToken: String, | ||
| val refreshToken: String | ||
| ) |
89 changes: 89 additions & 0 deletions
89
CT-auth/src/main/kotlin/com/chuseok22/ctauth/application/service/AuthService.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| package com.chuseok22.ctauth.application.service | ||
|
|
||
| import com.chuseok22.ctauth.application.dto.request.LoginRequest | ||
| import com.chuseok22.ctauth.application.dto.request.ReissueRequest | ||
| import com.chuseok22.ctauth.application.dto.response.LoginResponse | ||
| import com.chuseok22.ctauth.application.dto.response.ReissueResponse | ||
| import com.chuseok22.ctauth.core.token.TokenManager | ||
| import com.chuseok22.ctauth.core.token.TokenProvider | ||
| import com.chuseok22.ctcommon.application.exception.CustomException | ||
| import com.chuseok22.ctcommon.application.exception.ErrorCode | ||
| import com.chuseok22.ctmember.infrastructure.entity.Member | ||
| import com.chuseok22.ctmember.infrastructure.repository.MemberRepository | ||
| import com.chuseok22.sejongportallogin.core.SejongMemberInfo | ||
| import com.chuseok22.sejongportallogin.infrastructure.SejongPortalLoginService | ||
| import io.github.oshai.kotlinlogging.KotlinLogging | ||
| import org.springframework.stereotype.Service | ||
| import org.springframework.transaction.annotation.Transactional | ||
|
|
||
| private val log = KotlinLogging.logger { } | ||
|
|
||
| @Service | ||
| class AuthService( | ||
| private val sejongPortalLoginService: SejongPortalLoginService, | ||
| private val memberRepository: MemberRepository, | ||
| private val tokenProvider: TokenProvider, | ||
| private val tokenManager: TokenManager | ||
| ) { | ||
|
|
||
| @Transactional | ||
| fun login(request: LoginRequest): LoginResponse { | ||
| val sejongMemberInfo = sejongPortalLogin(request.sejongPortalId, request.sejongPortalPw) | ||
| val studentNumber = sejongMemberInfo.studentId | ||
| val name = sejongMemberInfo.name | ||
|
|
||
|
|
||
| val member = memberRepository.findByStudentNumberAndDeletedFalse(studentNumber) | ||
| ?: run { | ||
| log.info { "신규 회원 로그인: 학번=$studentNumber, 이름=$name" } | ||
| val newMember = Member.create(studentNumber, name) | ||
| memberRepository.save(newMember) | ||
| } | ||
|
|
||
| // 토큰 발급 | ||
| val tokenPair = tokenManager.createTokenPair(member.id.toString()) | ||
| tokenManager.saveRefreshTokenTtl(member.id.toString(), tokenPair.refreshToken) | ||
|
|
||
| log.info { "로그인 성공: 학번=$studentNumber, 이름=$name" } | ||
|
|
||
| return LoginResponse( | ||
| studentNumber = studentNumber, | ||
| name = name, | ||
| accessToken = tokenPair.accessToken, | ||
| refreshToken = tokenPair.refreshToken | ||
| ) | ||
| } | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| fun reissue(request: ReissueRequest): ReissueResponse { | ||
| log.debug { "토큰 재발급을 진행합니다" } | ||
| val memberId = tokenProvider.getMemberId(request.refreshToken) | ||
|
|
||
| tokenManager.validateSavedToken(request.refreshToken) | ||
|
|
||
| log.debug { "새로운 accessToken, refreshToken 발급" } | ||
| val tokenPair = tokenManager.createTokenPair(memberId) | ||
| tokenManager.saveRefreshTokenTtl(memberId, tokenPair.refreshToken) | ||
|
|
||
| return ReissueResponse( | ||
| accessToken = tokenPair.accessToken, | ||
| refreshToken = tokenPair.refreshToken | ||
| ) | ||
| } | ||
|
|
||
| fun logout(member: Member) { | ||
| val memberId = member.id | ||
| log.debug { "로그아웃을 진행합니다: 회원=$memberId" } | ||
| log.debug { "기존에 저장된 refreshToken 삭제" } | ||
| tokenManager.removeRefreshTokenTtl(memberId.toString()) | ||
| } | ||
|
|
||
| private fun sejongPortalLogin(sejongPortalId: String, sejongPortalPw: String): SejongMemberInfo { | ||
| try { | ||
| log.debug { "세종대학교 포털 로그인을 시도합니다: $sejongPortalId" } | ||
| return sejongPortalLoginService.getMemberAuthInfos(sejongPortalId, sejongPortalPw) | ||
| } catch (e: Exception) { | ||
| log.error(e) { "세종대학교 포털 로그인 중 오류 발생: ${e.message}" } | ||
| throw CustomException(ErrorCode.SEJONG_PORTAL_LOGIN_FAILED) | ||
| } | ||
| } | ||
| } | ||
24 changes: 24 additions & 0 deletions
24
CT-auth/src/main/kotlin/com/chuseok22/ctauth/core/token/TokenManager.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package com.chuseok22.ctauth.core.token | ||
|
|
||
| interface TokenManager { | ||
|
|
||
| /** | ||
| * accessToken, refreshToken Pair 생성 | ||
| */ | ||
| fun createTokenPair(memberId: String): TokenPair | ||
|
|
||
| /** | ||
| * refreshToken TTL 저장 | ||
| */ | ||
| fun saveRefreshTokenTtl(memberId: String, refreshToken: String) | ||
|
|
||
| /** | ||
| * refreshToken TTL 삭제 | ||
| */ | ||
| fun removeRefreshTokenTtl(memberId: String) | ||
|
|
||
| /** | ||
| * Redis에 저장된 토큰인지 검증 | ||
| */ | ||
| fun validateSavedToken(token: String) | ||
| } |
6 changes: 6 additions & 0 deletions
6
CT-auth/src/main/kotlin/com/chuseok22/ctauth/core/token/TokenPair.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package com.chuseok22.ctauth.core.token | ||
|
|
||
| data class TokenPair( | ||
| val accessToken: String, | ||
| val refreshToken: String | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
CT-auth/src/main/kotlin/com/chuseok22/ctauth/infrastructure/jwt/JwtManager.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| package com.chuseok22.ctauth.infrastructure.jwt | ||
|
|
||
| import com.chuseok22.ctauth.core.token.TokenManager | ||
| import com.chuseok22.ctauth.core.token.TokenPair | ||
| import com.chuseok22.ctauth.core.token.TokenProvider | ||
| import com.chuseok22.ctauth.core.token.TokenStore | ||
| import com.chuseok22.ctauth.infrastructure.properties.JwtProperties | ||
| import com.chuseok22.ctauth.infrastructure.util.AuthUtil | ||
| import com.chuseok22.ctcommon.application.exception.CustomException | ||
| import com.chuseok22.ctcommon.application.exception.ErrorCode | ||
| import io.github.oshai.kotlinlogging.KotlinLogging | ||
| import io.jsonwebtoken.ExpiredJwtException | ||
| import org.springframework.stereotype.Component | ||
|
|
||
| private val log = KotlinLogging.logger { } | ||
|
|
||
| @Component | ||
| class JwtManager( | ||
| private val tokenProvider: TokenProvider, | ||
| private val tokenStore: TokenStore, | ||
| private val jwtProperties: JwtProperties | ||
| ) : TokenManager { | ||
|
|
||
| override fun createTokenPair(memberId: String): TokenPair { | ||
| return TokenPair( | ||
| accessToken = tokenProvider.createAccessToken(memberId), | ||
| refreshToken = tokenProvider.createRefreshToken(memberId) | ||
| ) | ||
| } | ||
|
|
||
| override fun saveRefreshTokenTtl(memberId: String, refreshToken: String) { | ||
| log.debug { "Redis에 refreshToken을 저장합니다" } | ||
| val key = getKey(memberId) | ||
| tokenStore.save(key, refreshToken, jwtProperties.refreshExpMillis) | ||
| } | ||
|
|
||
| override fun removeRefreshTokenTtl(memberId: String) { | ||
| log.debug { "Redis에 저장된 refreshToken을 삭제합니다: 회원=$memberId" } | ||
| val key = getKey(memberId) | ||
| tokenStore.remove(key) | ||
| } | ||
|
|
||
| override fun validateSavedToken(token: String) { | ||
|
|
||
| val memberId = try { | ||
| tokenProvider.getMemberId(token) | ||
| } catch (e: ExpiredJwtException) { | ||
| log.warn(e) { "만료된 refreshToken 사용 시도" } | ||
| throw e | ||
| } catch (e: Exception) { | ||
| log.warn(e) { "유효하지 않은 refreshToken 사용 시도" } | ||
| throw CustomException(ErrorCode.INVALID_JWT) | ||
| } | ||
|
|
||
| val key = getKey(memberId) | ||
| val savedToken = tokenStore.get(key) ?: run { | ||
| log.warn { "Redis에 refreshToken이 존재하지 않습니다: 회원=$memberId" } | ||
| throw CustomException(ErrorCode.INVALID_JWT) | ||
| } | ||
|
|
||
| if (savedToken != token) { | ||
| log.warn { "유효하지 않은 refreshToken 사용 시도: $memberId" } | ||
| throw CustomException(ErrorCode.INVALID_JWT) | ||
| } | ||
| } | ||
|
|
||
| private fun getKey(memberId: String): String { | ||
| return AuthUtil.getRefreshTokenTtlKey(memberId) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
개인정보 로깅 검토 필요
학번(
studentNumber)과 이름(name)은 개인정보에 해당할 수 있습니다.info레벨 로깅은 프로덕션 환경에서도 기록되므로, 개인정보보호법 및 내부 정책에 따라 마스킹 처리하거나debug레벨로 변경하는 것을 고려하세요.🔒 마스킹 처리 예시
Also applies to: 47-47
🤖 Prompt for AI Agents