java.lang.ClassCastException: class java.lang.String cannot be cast to class com.teamsparta.member.global.auth.UserPrincipal (java.lang.String is in module java.base of loader 'bootstrap'; com.teamsparta.member.global.auth.UserPrincipal is in unnamed module of loader 'app')
@Transactional
fun login(request: LoginRequest): LoginResponse {
val authenticatedEmail = AuthenticationUtil.getUserEmail()
val member = memberRepository.findMemberByEmail(authenticatedEmail) ?: throw Exception("등록된 멤버가 아닙니다")//NosuchEntityExeption("MEMBER")
val jwt = jwtPlugin.generateJwt(member)
로그인을 하는 단계가 토큰을 받는 단계인데 아직 컨텍스트 홀더에 담기지 않았는데 받지도 않은 비어있는 authentication 안에서 이메일을 꺼내오려고 했다.
NullPointerException이 발생했는데 오류문을 읽어보니 subject(토큰제목)가 비어있으면 안된다고 적혀있었다.
이 오류는 실제 값이 아닌 null을 가지고 있는 객체/변수를 호출할 때 발생하는 예외라고 한다.
디버깅을 해서 payload를 보니 sb
: 서브젝트가 없었다.
토큰을 생성할 때 서브젝트를 같이 빌드하지 않아서 subject
가 null 값이 나왔다.
fun generateJwt(member: Member): LoginResponse {
val accessToken = generateToken(member)
val refreshToken = generateRefreshToken(member)
return LoginResponse(accessToken, refreshToken)
}
private fun generateToken(member: Member): String {
val claims = mapOf(
"nickName" to member.nickName,
"email" to member.email,
"role" to member.role
)
return Jwts.builder()
.subject(member.id.toString())
.issuer(issuer)
.issuedAt(Date.from(Instant.now()))
.claims(claims)
.signWith(key)
.expiration(Date.from(Instant.now().plus(Duration.ofHours(accessTokenExpirationHour))))
.compact()
}
private fun generateRefreshToken(member: Member): String {
val emptyClaims: Map<String, Any> = emptyMap()
return Jwts.builder()
.subject(member.id.toString())
.issuer(issuer)
.issuedAt(Date.from(Instant.now()))
.claims(emptyClaims)
.signWith(key)
.expiration(Date.from(Instant.now().plus(Duration.ofHours(refreshTokenExpirationHour))))
.compact()
}
generateToken 메서드에 .subject(member.id.toString())를 추가하고
generateRefreshToken 메서드에도 member 인자를 추가하고 id값을 문자열로 바꿔 subject를 추가해 오류를 수정했다.