-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJwtHandler.java
More file actions
109 lines (92 loc) · 4.11 KB
/
JwtHandler.java
File metadata and controls
109 lines (92 loc) · 4.11 KB
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package com.gpt.geumpumtabackend.global.jwt;
import com.gpt.geumpumtabackend.user.domain.UserRole;
import com.gpt.geumpumtabackend.token.domain.RefreshToken;
import com.gpt.geumpumtabackend.token.domain.Token;
import com.gpt.geumpumtabackend.token.repository.RefreshTokenRepository;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import org.springframework.transaction.annotation.Transactional;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
public class JwtHandler {
private final JwtProperties jwtProperties;
private final SecretKey secretKey;
private final RefreshTokenRepository refreshTokenRepository;
public static final String USER_ID = "USER_ID";
public static final String USER_ROLE = "ROLE_USER";
private static final String KEY_ROLE = "role";
private static final String IS_WITHDRAWN = "WITHDRAWN";
private static final long MILLI_SECOND = 1000L;
public JwtHandler(JwtProperties jwtProperties, RefreshTokenRepository refreshTokenRepository) {
this.jwtProperties = jwtProperties;
this.refreshTokenRepository = refreshTokenRepository;
secretKey = new SecretKeySpec(jwtProperties.getSecretKey().getBytes(StandardCharsets.UTF_8), Jwts.SIG.HS256.key().build().getAlgorithm());
}
@Transactional
public Token createTokens(JwtUserClaim jwtUserClaim) {
Map<String, Object> tokenClaims = this.createClaims(jwtUserClaim);
Date now = new Date(System.currentTimeMillis());
long accessTokenExpireIn = jwtProperties.getAccessTokenExpireIn();
String accessToken = Jwts.builder()
.claims(tokenClaims)
.issuedAt(now)
.expiration(new Date(now.getTime() + accessTokenExpireIn * MILLI_SECOND))
.signWith(secretKey)
.compact();
String refreshToken = UUID.randomUUID().toString();
long refreshTokenExpireIn = jwtProperties.getRefreshTokenExpireIn();
RefreshToken refreshTokenEntity = new RefreshToken(jwtUserClaim.userId(), refreshToken, refreshTokenExpireIn);
if(refreshTokenRepository.existsByUserId(jwtUserClaim.userId()))
refreshTokenRepository.deleteByUserId(jwtUserClaim.userId());
refreshTokenRepository.save(refreshTokenEntity);
return Token.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.build();
}
public Map<String, Object> createClaims(JwtUserClaim jwtUserClaim) {
return Map.of(
USER_ID, jwtUserClaim.userId(),
USER_ROLE, jwtUserClaim.role(),
IS_WITHDRAWN, jwtUserClaim.withdrawn()
);
}
// 재발급을 위해 token이 만료되었더라도 claim을 반환하는 메서드
public Optional<JwtUserClaim> getClaims(String token) {
try {
Claims claims = Jwts.parser()
.verifyWith(secretKey)
.build()
.parseSignedClaims(token)
.getPayload();
return Optional.of(this.convert(claims));
} catch (ExpiredJwtException e) {
Claims claims = e.getClaims();
return Optional.of(this.convert(claims));
} catch (Exception e) {
return Optional.empty();
}
}
public JwtUserClaim convert(Claims claims) {
return new JwtUserClaim(
claims.get(USER_ID, Long.class),
UserRole.valueOf(claims.get(USER_ROLE, String.class)),
claims.get(IS_WITHDRAWN, Boolean.class)
);
}
// 필터에서 토큰의 상태를 검증하기 위한 메서드 exception은 사용하는 곳에서 처리
public JwtUserClaim parseToken(String token) {
Claims claims = Jwts.parser()
.verifyWith(secretKey)
.build()
.parseSignedClaims(token)
.getPayload();
return this.convert(claims);
}
}