Kotlin, Auth with JWT 1장

git source 샘플소스 링크

사전작업

build.gradle

1
implementation("com.auth0:java-jwt:3.8.1")

jwt관련 부분 추가!

우선 토큰을 생성해보자

SampleTokenService.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Service
class SampleTokenService {


companion object {

val ISSURE = "BEANBROKER"
val SCRET = "1234"

}

fun publish(id: Long, authType: String): String? {

//60 * 60 * 24
val now = LocalDateTime.now()
val expiredAt = now.plusSeconds(86400)

return JWT.create()
.withClaim("id", id)
.withClaim("authType", authType)
.withIssuedAt(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()))
.withIssuer(ISSURE)
.withExpiresAt(Date.from(expiredAt.atZone(ZoneId.systemDefault()).toInstant()))
.sign(Algorithm.HMAC256(SCRET))


}


}
  1. 해당 토큰의 만료기간은 하루
  2. ISSURE: 토큰 발급자

SampleAuthTests.class

테스트코드 짜기 귀찮으니 콘솔로 확인하자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

@RunWith(SpringRunner::class)
@SpringBootTest
class SampleAuthTests {


@Autowired
private lateinit var tokenService: SampleTokenService


@Test
fun createToken() {


val token = tokenService.publish(1000, "USER")


println(token)


}

}

결과 : eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJCRUFOQlJPS0VSIiwiaWQiOjEwMDAsImF1dGhUeXBlIjoiVVNFUiIsImV4cCI6MTU2ODAxNTE1MywiaWF0IjoxNTY3OTI4NzUzfQ.-9_1Cq7Tc19lo3lcNc0G4Y_CjVZDWmoHzWAE7iWNWYM

토큰을 생성했으니 토큰을 decode해보자

SampleTokenService.class 에 추가

1
2
3
4
5
6
7
8
9
fun decodeToken(token : String) {


val jwt = JWT.require(Algorithm.HMAC256(SCRET))
.withIssuer(ISSURE)
.build()
.verify(token)

}

위와같이 jwt 생성 및 디코드를 진행해보았다.

자… 그럼 이걸 서비스 로직에서 쓰일 정도로 올리는 작업을 해보자

리팩토링을 해보자

  • 우선 client에게 제공할수 있도록 데이터를 만들어보자

BeanbrokerToken.class

1
2
3
4
5
class BeanbrokerToken {

var token: String = ""
var expireDate: LocalDateTime? = null
}

token : 방금 위에서 생성한 토큰
expireDate : 만료시간(클라이언트에게 만료시간 전달)

SampleTokenService.class createToken변경

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fun createToken(id: Long, authType: String): BeanbrokerToken {

//60 * 60 * 24
val now = LocalDateTime.now()
val expiredAt = now.plusSeconds(86400)

return BeanbrokerToken().apply {
this.expireDate = expiredAt
this.token = JWT.create()
.withClaim("id", id)
.withClaim("authType", authType)
.withIssuedAt(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()))
.withIssuer(ISSURE)
.withExpiresAt(Date.from(expiredAt.atZone(ZoneId.systemDefault()).toInstant()))
.sign(Algorithm.HMAC256(SCRET))
}

}

만약에 위와같이 하고 사용하게 한다면?

header에 토큰 정보를 심어 보낸다고 가정하였을때 컨트롤러 단에서 헤더 매번까서 확인하는게 좋을가요…? 아니면 interceptor(AOP)에서 검증하는게 좋을가요?

라는 고민을 하였을 때 당연히 후자! 해당 부분을 추가해보자 2장에서