본문 바로가기
TIL

TIL - 24.01.11

by JHBang 2024. 1. 11.

과제 진행 상황

어제에 이어 과제 작성에 열을 가했다.

 

그 결과 오늘 프로젝트 요구사항에 부합하는 구현 코드를 완성했다.

 

팀원을 모집하는 포스트의 기본적인 CRUD부터 팀원 신청 내역을 조회하고 수락/거절하는 기능까지 구현했다.

 

 

 

사용자 인증 기능

 

눈여겨 볼 것은 각 서비스의 사용자 인증 기능이였다. 예를 들어 로그인하지 않은 사용자는 글을 작성할 수 없어야 하며, 팀장이 작성한 모집 포스트를 보고 참가자가 신청을 하면 이 요청에 대한 응답은 팀 모집글을 작성한 팀장만이 가능해야 한다.

 

이 기능에 대해선 팀원 중 한 분이 알려주신 코드가 있다.

 

@Component
class BasicAuth(
	private val request: HttpServletRequest,
	private val memberEntityRepository: MemberEntityRepository
) : IAuth {

	// 현재 사용자의 키 받아옴
	fun getCurrentMemberKey(): String =
		request.getHeader("Authorization")?.split(" ")?.get(1) ?: TODO("로그인 안되어 있습니다. exception 만들기")


	// 현재 사용자의 엔티티 받아옴
	override fun getCurrentMemberEntity(): MemberEntity =
		getCurrentMemberKey().split(" ")[1].let {
			memberEntityRepository.findByKey(it) ?: TODO("로그인 상태 확인. exception 만들기")
		}

	override fun getType(): String = "basic"

	// 키 생성
	override fun generateKey(signDto: SignDto): String =
		Base64Util.encode("${signDto.id}:${signDto.password}")

	// 접근권한 확인
	override fun <T> checkPermission(member: MemberEntity, func: () -> T): T =
		getCurrentMemberKey()
			.let { if (it != member.key) TODO("접근 권한 없음 에러. exception 만들기") }
			.let { func.invoke() }
}

 

MemberEntity 엔 기본적인 사용자 정보가 있다. 

 

위 코드는 기본적인 사용자 인증과 권한을 부여하는 코드이다. 처음 받았을 때 한줄 한줄 뜯어보며 각 메소드가 어떤 역할을 하는지 분석했고, 이를 주석으로 달아놨다.

 

HttpSrevletEntity같은 처음 보는 엔티티도 있었고 헤더에서 사용자 키를 가져와 사용하는 방식도 생소했다. 

 

아직 로그인과 회원가입 서비스는 구현이 안되어있어( 추가구현 과제이다.) 위의 메소드를 모두 사용하진 않지만 그래도 몇가지 메소드를 사용해 코드에 추가했다.

 

fun chooseApproveOrNot(
        postId: Long,
        participantsId: Long,
        request: ChooseApproveRequest
    ): TeamParticipationResponse{
        val recruitmentPost = recruitPostRepository.findByIdOrNull(postId) ?: TODO("에외처리")
        val participationRequest = teamParticipationRepository.findByIdOrNull(participantsId) ?: TODO("에외처리")
        auth.checkPermission(recruitmentPost.memberEntity) {
        
        ....
        }
    return teamParticipationRepository.save(participationRequest).toResponseDTO()
    }
}

 

위 코드는 checkPermissionRequest 를 이용해 팀 참가 신청에 대한 응답을 구현하는 코드이다.

 

recruimentPost에 선택된 팀에 대한 엔티티가 들어가고 participationRequest 에 승인 여부에 대한 요청 엔티티가 들어간다.

 

이 때 checksumPermission 에 recruimentPost 의 memberEntity프로퍼티를 넣어준다. 팀 엔티티는 memberEntity를 FK로 가지고 있다.

 

checkPermission을 자세히 보자.

override fun <T> checkPermission(member: MemberEntity, func: () -> T): T =
		getCurrentMemberKey()
			.let { if (it != member.key) TODO("접근 권한 없음 에러. exception 만들기") }
			.let { func.invoke() }
}

 

현재 로그인해 있는 사용자의 key와 인자로 받은 memberEntity의 key와 비교하여 같은 경우 함수를 실행한다.

 

즉 위 코드 chooseApproveOrNot에서 현재 로그인 중인 사용자와 팀 모집글을 작성한 사용자가 동일한 경우에만 서비스 로직을 실행한다는 뜻이다.

 

 

 

 

이런 방법은  보안에 취약하다는 걸 알려 주시면서 팀장님은 코드를 제공해 주셨다. 좀 더 보안성이 높은 코드를 구현하는 법에 대해 더 알아봐야겠다.

 

내일은 전체적으로 코드를 다시 읽어보고 어색한 부분이나 불필요한 부분을 수정할 예정이다. 테스트 또한 진행해 봐야겠다.

'TIL' 카테고리의 다른 글

TIL - 24.01.17  (0) 2024.01.17
TIL - 24.01.15 (팀 프로젝트 회고)  (1) 2024.01.15
TIL - 24.01.09  (0) 2024.01.09
TIL - 24.01.08  (1) 2024.01.08
TIL - 23.12.28  (0) 2023.12.28