Skip to content

Commit 3f12e6b

Browse files
committed
[feat] : Save RefreshToken to Redis #8
1 parent 5981346 commit 3f12e6b

File tree

3 files changed

+70
-11
lines changed

3 files changed

+70
-11
lines changed

src/main/java/org/dfbf/soundlink/domain/user/service/UserService.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.springframework.http.HttpHeaders;
2828
import org.springframework.http.ResponseCookie;
2929
import org.springframework.http.ResponseEntity;
30+
import org.springframework.security.core.context.SecurityContextHolder;
31+
import org.springframework.security.core.userdetails.UserDetails;
3032
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
3133
import org.springframework.stereotype.Service;
3234

@@ -177,6 +179,7 @@ public boolean checkNickName(String nickName){
177179
return userRepository.existsByNickName(nickName);
178180
}
179181

182+
//refreshToken을 쿠키로 설정
180183
public ResponseCookie getRefreshToken(String refreshToken) {
181184
return ResponseCookie
182185
.from("REFRESHTOKEN", refreshToken)
@@ -204,43 +207,42 @@ public ResponseResult login(LoginReqDto loginReqDto, HttpServletResponse respons
204207
String accessToken = jwtProvider.createAccessToken(user.getUserId());
205208
String refreshToken = jwtProvider.createRefreshToken(user.getUserId());
206209

207-
// System.out.println("Access Token: " + accessToken);
208-
// System.out.println("Refresh Token: " + refreshToken);
209210

210-
//헤더에 refreshToken 추가
211+
//refreshToken - 쿠키
211212
ResponseCookie refreshCookie = getRefreshToken(refreshToken);
212213
response.setHeader("Set-Cookie", refreshCookie.toString());
213214

214-
//바디에 accessToken 포함
215+
//accessToken - 바디
215216
Map<String, String> responseBody = new HashMap<>();
216217
responseBody.put("accessToken", accessToken);
217218

218219
return new ResponseResult(responseBody);
219220
} catch (Exception e) {
220221
System.out.println("[ERROR] " + e.getMessage());
221-
return new ResponseResult(ErrorCode.DB_ERROR);
222+
return new ResponseResult(ErrorCode. INTERNAL_SERVER_ERROR);
222223
}
223224
}
224225

225226
//로그아웃
226227
public ResponseResult logout(HttpServletResponse response) {
227228
try {
228-
//토큰 삭제
229+
//클라이언트 - 토큰 삭제
229230
ResponseCookie refreshCookie = ResponseCookie
230231
.from("REFRESHTOKEN", "") // 추후 토큰값 추가
231232
.domain("localhost")
232233
.path("/")
233234
.httpOnly(true)
234235
.maxAge(0)
235236
.build();
237+
response.setHeader("Set-Cookie", refreshCookie.toString());//쿠키 삭제 요청
236238

237-
response.setHeader("Set-Cookie", refreshCookie.toString());//삭제 요청
238239
return new ResponseResult(ErrorCode.SUCCESS);
239240

240241
} catch (Exception e) {
241-
return new ResponseResult(ErrorCode.DB_ERROR,"로그아웃 중 오류가 발생했습니다.");
242+
return new ResponseResult(ErrorCode. INTERNAL_SERVER_ERROR,"로그아웃 중 오류가 발생했습니다.");
242243
}
243244
}
244245

245246

247+
246248
}

src/main/java/org/dfbf/soundlink/global/auth/JwtProvider.java

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22

33
import ch.qos.logback.core.subst.Token;
44
import io.jsonwebtoken.security.Keys;
5+
import io.jsonwebtoken.security.SignatureException;
6+
import jakarta.servlet.http.Cookie;
7+
import jakarta.servlet.http.HttpServletRequest;
8+
import org.springframework.beans.factory.annotation.Autowired;
59
import org.springframework.beans.factory.annotation.Value;
10+
import org.springframework.data.redis.core.RedisTemplate;
611
import org.springframework.stereotype.Component;
712
import io.jsonwebtoken.*;
813

914
import javax.crypto.SecretKey;
1015
import java.util.Date;
16+
import java.util.concurrent.TimeUnit;
1117

1218
@Component
1319
public class JwtProvider {
@@ -19,8 +25,11 @@ public class JwtProvider {
1925
@Value("${REFRESH_TOKEN_EXPIRATION_TIME}")
2026
private long REFRESH_EXPIRATION_TIME;
2127

22-
//시크릿 키 생성
23-
private final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);;
28+
//시크릿 키 자동 생성
29+
private final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
30+
31+
@Autowired
32+
private RedisTemplate<String, String> redisTemplate;
2433

2534
//Access 토큰
2635
public String createAccessToken(long userId) {
@@ -45,8 +54,48 @@ public String createRefreshToken(long userId) {
4554
.setExpiration(new Date(now.getTime()+REFRESH_EXPIRATION_TIME))
4655
.signWith(SECRET_KEY, SignatureAlgorithm.HS256)
4756
.compact();
57+
try {
58+
redisTemplate.opsForValue().set("refreshToken: "+userId, refreshToken,REFRESH_EXPIRATION_TIME, TimeUnit.MILLISECONDS);
59+
return refreshToken;
60+
} catch (Exception e) {
61+
System.out.println("[Redis] RefreshToken save failed: " + e.getMessage());
62+
return null;
63+
}
64+
}
65+
66+
//토큰 검증(변조, 만료, 올바른 형식)
67+
public boolean validateToken(String token){
68+
try {
69+
Jwts.parserBuilder()
70+
.setSigningKey(SECRET_KEY) //서명 검증
71+
.build()
72+
.parseClaimsJws(token); //토큰 유효한지 확인.
73+
return true;
74+
} catch (Exception e) {
75+
System.out.println("[ERROR] Token validation failed: " + e.getMessage());
76+
return false;
77+
}
78+
}
79+
80+
//액세스토큰 추출
81+
public String resolveAccessToken(HttpServletRequest request) {
82+
String bearerToken = request.getHeader("Authorization"); //토큰을 헤더에 포함했는지
83+
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
84+
return bearerToken.substring(7);
85+
}
86+
return null;
87+
}
4888

49-
return refreshToken;
89+
//리프레시토큰 추출
90+
public String resolveRefreshToken(HttpServletRequest request) {
91+
if(request.getCookies() != null){
92+
for (Cookie cookie : request.getCookies()) {
93+
if("REFRESHTOKEN".equals(cookie.getName())){ //REFRESHTOKEN 쿠키 찾아서 해당 값 반환
94+
return cookie.getValue();
95+
}
96+
}
97+
}
98+
return null;
5099
}
51100

52101
}

src/main/java/org/dfbf/soundlink/global/auth/TokenProperties.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
@ConfigurationProperties(prefix = "token")
99
public class TokenProperties {
1010
private long refreshTokenExpirationTime;
11+
private long accessTokenExpirationTime;
1112

1213
public long getRefreshTokenExpirationTime(){
1314
return refreshTokenExpirationTime;
@@ -16,4 +17,11 @@ public long getRefreshTokenExpirationTime(){
1617
public void setRefreshTokenExpirationTime(long refreshTokenExpirationTime){
1718
this.refreshTokenExpirationTime = refreshTokenExpirationTime;
1819
}
20+
public long getAccessTokenExpirationTime() {
21+
return accessTokenExpirationTime;
22+
}
23+
24+
public void setAccessTokenExpirationTime(long accessTokenExpirationTime) {
25+
this.accessTokenExpirationTime = accessTokenExpirationTime;
26+
}
1927
}

0 commit comments

Comments
 (0)