Skip to content

Commit

Permalink
✨ feat: refreshToken 재발급 로직 구현 (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
synoti21 committed Jan 24, 2024
1 parent d27afbb commit 35e95b8
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
String token = jwtTokenProvider.resolveToken((HttpServletRequest) request);

// 토큰이 유효하다면
if (token != null && jwtTokenProvider.validateToken(token)) {
if (token != null && jwtTokenProvider.validateAccessToken(token)) {
// 토큰으로부터 유저 정보를 받아
Authentication authentication = jwtTokenProvider.getAuthentication(token);
// SecurityContext 에 객체 저장
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.diareat.diareat.auth.component;

import com.diareat.diareat.util.api.ResponseCode;
import com.diareat.diareat.util.exception.BaseException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
Expand Down Expand Up @@ -80,7 +82,7 @@ public Long getUserPk(String token) {
}

// 토큰 유효성, 만료일자 확인
public boolean validateToken(String jwtToken) {
public boolean validateAccessToken(String jwtToken) {
try {
Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwtToken);
return !claims.getBody().getExpiration().before(new Date());
Expand All @@ -89,6 +91,13 @@ public boolean validateToken(String jwtToken) {
}
}

public void validateRefreshToken(Long userPK, String refreshToken) {
String redisRefreshToken = redisTemplate.opsForValue().get(String.valueOf(userPK));
if (redisRefreshToken == null || !redisRefreshToken.equals(refreshToken)) {
throw new BaseException(ResponseCode.REFRESH_TOKEN_VALIDATION_FAILURE);
}
}

// Request의 Header에서 token 값 가져오기
public String resolveToken(HttpServletRequest request) {
return request.getHeader("accessToken");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,47 @@ public class AuthController {
@PostMapping("/login")
public ApiResponse<ResponseJwtDto> authCheck(@RequestHeader String accessToken) {
Long userId = kakaoAuthService.isSignedUp(accessToken); // 유저 고유번호 추출
String jwt = (userId == null) ? null : jwtTokenProvider.createAccessToken(userId.toString()); // 고유번호가 null이 아니라면 Jwt 토큰 발급
return ApiResponse.success(ResponseJwtDto.of(userId, jwt), ResponseCode.USER_LOGIN_SUCCESS.getMessage());

ResponseJwtDto responseJwtDto = (userId == null) ? null : ResponseJwtDto.builder()
.accessToken(jwtTokenProvider.createAccessToken(userId.toString()))
.refreshToken(jwtTokenProvider.createRefreshToken(userId.toString()))
.build();

return ApiResponse.success(responseJwtDto, ResponseCode.USER_LOGIN_SUCCESS.getMessage());
}

// 회원가입 (성공 시 Jwt 토큰 발급)
@Operation(summary = "[회원가입] 회원가입 및 토큰 발급", description = "신규 회원가입을 처리하고, 회원가입 성공 시 id와 Jwt 토큰을 발급합니다.")
@PostMapping("/join")
public ApiResponse<ResponseJwtDto> saveUser(@Valid @RequestBody JoinUserDto joinUserDto) {
Long userId = userService.saveUser(kakaoAuthService.createUserDto(joinUserDto));
String jwt = jwtTokenProvider.createAccessToken(userId.toString());
return ApiResponse.success(ResponseJwtDto.of(userId, jwt), ResponseCode.USER_CREATE_SUCCESS.getMessage());

ResponseJwtDto responseJwtDto = (userId == null) ? null : ResponseJwtDto.builder()
.accessToken(jwtTokenProvider.createAccessToken(userId.toString()))
.refreshToken(jwtTokenProvider.createRefreshToken(userId.toString()))
.build();

return ApiResponse.success(responseJwtDto, ResponseCode.USER_CREATE_SUCCESS.getMessage());
}

// 토큰 검증 (Jwt 토큰을 서버에 전송하여, 서버가 유효한 토큰인지 확인하고 True 혹은 예외 반환)
@Operation(summary = "[토큰 검증] 토큰 검증", description = "클라이언트가 가지고 있던 Jwt 토큰을 서버에 전송하여, 서버가 유효한 토큰인지 확인하고 OK 혹은 예외를 반환합니다.")
@GetMapping("/token")
public ApiResponse<Boolean> tokenCheck(@RequestHeader String jwtToken) {
return ApiResponse.success(jwtTokenProvider.validateToken(jwtToken), ResponseCode.TOKEN_CHECK_SUCCESS.getMessage());
public ApiResponse<Boolean> tokenCheck(@RequestHeader String accessToken) {
return ApiResponse.success(jwtTokenProvider.validateAccessToken(accessToken), ResponseCode.TOKEN_CHECK_SUCCESS.getMessage());
}

@Operation(summary = "[토큰 재발급] 토큰 재발급", description = "클라이언트가 가지고 있던 Refresh 토큰을 서버에 전송하여, 서버가 유효한 토큰인지 확인하고 OK 혹은 예외를 반환합니다.")
@PostMapping("/reissue")
public ApiResponse<ResponseJwtDto> reissueToken(@RequestHeader String refreshToken) {
Long userId = jwtTokenProvider.getUserPk(refreshToken);
jwtTokenProvider.validateRefreshToken(userId, refreshToken);

ResponseJwtDto responseJwtDto = (userId == null) ? null : ResponseJwtDto.builder()
.accessToken(jwtTokenProvider.createAccessToken(userId.toString()))
.refreshToken(jwtTokenProvider.createRefreshToken(userId.toString()))
.build();

return ApiResponse.success(responseJwtDto, ResponseCode.TOKEN_REISSUE_SUCCESS.getMessage());
}
}
10 changes: 4 additions & 6 deletions src/main/java/com/diareat/diareat/auth/dto/ResponseJwtDto.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package com.diareat.diareat.auth.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
@AllArgsConstructor
public class ResponseJwtDto {

private Long id;
private String jwt;

public static ResponseJwtDto of(Long id, String jwt) {
return new ResponseJwtDto(id, jwt);
}
private String accessToken;
private String refreshToken;
}
2 changes: 2 additions & 0 deletions src/main/java/com/diareat/diareat/util/api/ResponseCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public enum ResponseCode {

// 401 Unauthorized
TOKEN_VALIDATION_FAILURE(HttpStatus.UNAUTHORIZED, false, "토큰 검증 실패"),
REFRESH_TOKEN_VALIDATION_FAILURE(HttpStatus.UNAUTHORIZED, false, "Refresh 토큰 검증 실패"),

// 403 Forbidden
FORBIDDEN(HttpStatus.FORBIDDEN, false, "권한이 없습니다."),
Expand Down Expand Up @@ -56,6 +57,7 @@ public enum ResponseCode {
FOOD_RANK_READ_SUCCESS(HttpStatus.OK, true, "식습관 점수 기반 랭킹 조회 성공"),

TOKEN_CHECK_SUCCESS(HttpStatus.OK, true, "토큰 검증 완료"),
TOKEN_REISSUE_SUCCESS(HttpStatus.OK, true, "토큰 재발급 완료"),


// 201 Created
Expand Down

0 comments on commit 35e95b8

Please sign in to comment.