𝑟𝑒𝑓𝑟𝑒𝑠ℎ𝑇𝑜𝑘𝑒𝑛을 통해 𝑎𝑐𝑐𝑒𝑠𝑠𝑇𝑜𝑘𝑒𝑛 재발급
2025. 1. 22. 21:10ㆍTIL
이때까지 테스트를 할때는 accessToken의 만료기간이 1시간으로 설정되어있어서 정상적으로 잘 작동하는지 알고 있었으나 refreshToken을 도입하고 accessToken의 만료기간을 1분으로 짧게 설정하자 정상적으로 토큰이 재발급 되지 않는 상황을 발견하여 해당 코드를 수정하였다.
더보기
package hjp.hjchat.infra.security.jwt
import io.jsonwebtoken.ExpiredJwtException
import jakarta.servlet.FilterChain
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpHeaders.AUTHORIZATION
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource
import org.springframework.stereotype.Component
import org.springframework.web.filter.OncePerRequestFilter
@Component
class JwtAuthenticationFilter(
private val jwtTokenManager: JwtTokenManager,
) : OncePerRequestFilter() {
override fun doFilterInternal(
request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain
) {
var pureToken: String? = null
if (request.getHeader(AUTHORIZATION) != null && request.getHeader(AUTHORIZATION).startsWith("Bearer ")) {
pureToken = request.getHeader("Authorization").substring(7)
}
var refreshToken: String? = null
if (pureToken != null) {
jwtTokenManager.validateToken(pureToken).onSuccess {
val tokenType = it.payload.get(JwtTokenManager.TOKEN_TYPE_KEY, String::class.java)
val memberRole = it.payload.get(JwtTokenManager.MEMBER_ROLE_KEY, String::class.java)
val memberId: Long = it.payload.subject.toLong()
if (tokenType == TokenType.REFRESH_TOKEN_TYPE.name) {
return@onSuccess
}
val userPrincipal = UserPrincipal(memberId = memberId, memberRole = setOf(memberRole))
val authentication = JwtAuthenticationToken(
userPrincipal = userPrincipal, details = WebAuthenticationDetailsSource().buildDetails(request)
)
SecurityContextHolder.getContext().authentication = authentication
}.onFailure {
logger.debug("Token validation failed", it)
if (it is ExpiredJwtException) {
logger.info("토큰의 만료기간이 끝나서 validate되지 않았음!! ")
refreshToken = getRefreshTokenFromCookies(request)
logger.info("쿠키에서 가져온 refreshTOken값: $refreshToken")
if(refreshToken != null) {
logger.info(" 토큰의 만료기간이 지났고 refreshToken이 null이 아님!")
jwtTokenManager.validateRefreshToken(refreshToken!!)
val newAccessToken = jwtTokenManager.reissueAccessToken(refreshToken!!)
response.setHeader(HttpHeaders.AUTHORIZATION, "Bearer $newAccessToken")
logger.info("토큰 재발급 성공! $newAccessToken")
val tokenInfo = jwtTokenManager.getInfoToken(newAccessToken)
val userPrincipal = UserPrincipal(memberId = tokenInfo!!.memberId, memberRole = setOf(tokenInfo.memberRole))
val authentication = JwtAuthenticationToken(
userPrincipal = userPrincipal, details = WebAuthenticationDetailsSource().buildDetails(request)
)
SecurityContextHolder.getContext().authentication = authentication
}
}
else response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "인증 실패")
}
}
filterChain.doFilter(request, response)
}
}
private fun getRefreshTokenFromCookies(request: HttpServletRequest): String? {
return request.cookies
?.firstOrNull { it.name == "refreshToken" }
?.value
}
해당 코드는 내가 동작시키고싶을때마다 동작하는것이 아닌 매 HTTP 요청마다 실행이 되기때문에 logger.info를 이용하여 해당 코드를 실행하고 내가 의도한대로 값이 저장되고 전달이 되는지를 체크하였다.
토큰을 재발급 받을때 서버의 log
테스트 영상: https://www.youtube.com/watch?v=XlIqixuaY7o
'TIL' 카테고리의 다른 글
𝙒𝙚𝙗𝙎𝙤𝙘𝙠𝙚𝙩 통신에서 𝘼𝙘𝙘𝙚𝙨𝙨𝙏𝙤𝙠𝙚𝙣 재발급 받기 (연결 중에) (0) | 2025.01.24 |
---|---|
𝐖𝐞𝐛𝐒𝐨𝐜𝐤𝐞𝐭 통신에서 𝐀𝐜𝐜𝐞𝐬𝐬𝐓𝐨𝐤𝐞𝐧 재발급 받기 (최초 실행시) (0) | 2025.01.23 |
테스트환경에서 SSL/HTTPS 설정하기 (0) | 2025.01.15 |
Redis를 이용한 로그아웃 (0) | 2025.01.14 |
Swagger failed to load api definition 오류 (0) | 2025.01.13 |