Skip to content

Commit

Permalink
feat: 토큰 관리 API 추가 (#68)
Browse files Browse the repository at this point in the history
Co-authored-by: MingyeomKim <[email protected]>
  • Loading branch information
Mingyum-Kim and Mingyum-Kim authored Sep 17, 2023
1 parent b1534d1 commit d01c73f
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 11 deletions.
31 changes: 22 additions & 9 deletions src/main/java/com/backend/auth/jwt/TokenProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,9 @@
@Slf4j
@Component
public class TokenProvider {
private static final long ACCESS_TOKEN_EXPIRE_TIME = 1000 * 60 * 60 * 2; // 2시간
private Long accessTokenExpireTime = Long.valueOf(1000 * 60 * 60 * 2);

// private static final long ACCESS_TOKEN_EXPIRE_TIME = 1000 * 30; // 30초

private static final long REFRESH_TOKEN_EXPIRE_TIME = 1000 * 60 * 60 * 24 * 14; // 2주

// private static final long REFRESH_TOKEN_EXPIRE_TIME = 1000 * 60; // 1분
private Long refreshTokenExpireTime = Long.valueOf(1000 * 60 * 60 * 24 * 14);

private static final String TOKEN_HEADER_PREFIX = "Bearer ";

Expand All @@ -45,18 +41,18 @@ public class TokenProvider {

private final MemberRepository memberRepository;

public TokenProvider(@Value("${jwt.secret}") String secretKey, RefreshTokenService refreshTokenService, MemberRepository memberRepository){
public TokenProvider(@Value("${jwt.secret}") String secretKey, MemberRepository memberRepository){
this.memberRepository = memberRepository;
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
this.key = Keys.hmacShaKeyFor(keyBytes);
}

public String generateAccessToken(String uid){
return generateToken(uid, ACCESS_TOKEN_EXPIRE_TIME);
return generateToken(uid, accessTokenExpireTime);
}

public String generateRefreshToken(String uid){
return generateToken(uid, REFRESH_TOKEN_EXPIRE_TIME);
return generateToken(uid, refreshTokenExpireTime);
}

public String generateToken(String uid, Long expireTime){
Expand Down Expand Up @@ -130,4 +126,21 @@ public Authentication getAuthentication(String accessToken) {
UserDetails principal = new User(claims.getSubject(), "", authorities);
return new UsernamePasswordAuthenticationToken(principal, "", authorities);
}

public void updateAccessTokenExpireTime(Long expireTime){
accessTokenExpireTime = expireTime;
}

public void updateRefreshTokenExpireTime(Long expireTime){
refreshTokenExpireTime = expireTime;
}

public Long getAccessTokenExpireTime(){
return accessTokenExpireTime;
}

public Long getRefreshTokenExpireTime() {
return refreshTokenExpireTime;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
try {
String accessToken = tokenProvider.getToken(request.getHeader(AUTHORIZATION_HEADER));


// 토큰의 유효성을 검증
tokenProvider.validateToken(accessToken);
blackListService.checkBlackList(accessToken);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.backend.auth.presentation;

import com.backend.auth.application.OAuthService;
import com.backend.auth.application.RefreshTokenService;
import com.backend.auth.jwt.TokenProvider;
import com.backend.auth.presentation.dto.request.LoginRequestDto;
import com.backend.auth.presentation.dto.response.LoginResponse;
import com.backend.auth.presentation.dto.response.ReissueResponse;
Expand All @@ -26,7 +26,7 @@ public class OAuthController {

private final OAuthService oauthService;

private final RefreshTokenService refreshTokenService;
private final TokenProvider tokenProvider;

@Operation(summary = "소셜 로그인",
description = "카카오, 애플 서버에서 로그인한 사용자의 userId를 통해 access token과 refresh token을 반환합니다.")
Expand Down
50 changes: 50 additions & 0 deletions src/main/java/com/backend/auth/presentation/TokenController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.backend.auth.presentation;

import com.backend.auth.jwt.TokenProvider;
import com.backend.auth.presentation.dto.request.ExpireTimeRequest;
import com.backend.auth.presentation.dto.response.ExpireTimeResponse;
import com.backend.global.common.response.CustomResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import static com.backend.global.common.code.SuccessCode.SELECT_SUCCESS;
import static com.backend.global.common.code.SuccessCode.UPDATE_SUCCESS;

@Tag(name = "token", description = "토큰 관리 API입니다.")
@RequiredArgsConstructor
@RequestMapping("/token")
@RestController
public class TokenController {
private final TokenProvider tokenProvider;

@Operation(summary = "액세스 토큰 유효 시간 수정", description = "액세스 토큰의 유효 시간을 수정한다.")
@PutMapping("/access/expire")
public ResponseEntity<CustomResponse<Void>> updateAccessTokenExpireTime(@RequestBody ExpireTimeRequest expireTimeRequest){
tokenProvider.updateAccessTokenExpireTime(expireTimeRequest.toLong());
return CustomResponse.success(UPDATE_SUCCESS);
}

@Operation(summary = "리프레시 토큰 유효 시간 수정", description = "리프레시 토큰의 유효 시간을 수정한다.")
@PutMapping("/refresh/expire")
public ResponseEntity<CustomResponse<Void>> updateRefreshTokenExpireTime(@RequestBody ExpireTimeRequest expireTimeRequest){
tokenProvider.updateRefreshTokenExpireTime(expireTimeRequest.toLong());
return CustomResponse.success(UPDATE_SUCCESS);
}

@Operation(summary = "액세스 토큰 유효 시간 조회", description = "액세스 토큰의 유효 시간을 초 단위로 조회한다.")
@GetMapping("/access/expire")
public ResponseEntity<CustomResponse<ExpireTimeResponse>> getAccessTokenExpireTime(){
return CustomResponse.success(SELECT_SUCCESS, ExpireTimeResponse.from(tokenProvider.getAccessTokenExpireTime()));
}

@Operation(summary = "리프레시 토큰 유효 시간 조회", description = "리프레시 토큰의 유효 시간을 초 단위로 조회한다.")
@GetMapping("/refresh/expire")
public ResponseEntity<CustomResponse<ExpireTimeResponse>> getRefreshTokenExpireTime(){
return CustomResponse.success(SELECT_SUCCESS, ExpireTimeResponse.from(tokenProvider.getRefreshTokenExpireTime()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.backend.auth.presentation.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;

public record ExpireTimeRequest(
@Schema(description = "만료 기한의 일수", example = "14")
Long days,

@Schema(description = "만료 기한의 시간", example = "0")
Long hours,

@Schema(description = "만료 기한의 분", example = "0")
Long minutes,

@Schema(description = "만료 기한의 초", example = "0")
Long seconds
) {
public Long toLong() {
Long expireTime = 1000L;

if(days!= 0) expireTime *= (days * 24 * 60 * 60);
if(hours != 0) expireTime *= (hours * 60 * 60);
if(minutes != 0) expireTime *= (minutes * 60);
if(seconds != 0) expireTime *= (seconds * 60);
return expireTime;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.backend.auth.presentation.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;

public record ExpireTimeResponse(
@Schema(description = "만료 기한의 일수", example = "14")
Long days,

@Schema(description = "만료 기한의 시간", example = "0")
Long hours,

@Schema(description = "만료 기한의 분", example = "0")
Long minutes,

@Schema(description = "만료 기한의 초", example = "0")
Long seconds
) {
public static ExpireTimeResponse from(Long expireTime) {
expireTime /= 1000;

Long days = expireTime / (24 * 60 * 60);
if(days != 0) expireTime %= days;

Long hours = expireTime / (60 * 60);
if(hours != 0) expireTime %= hours;

Long minutes = expireTime / 60;
if(minutes != 0) expireTime %= minutes;

Long seconds = expireTime / 60;
return new ExpireTimeResponse(days, hours, minutes, seconds);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
public class SecurityConfig {

private final TokenProvider tokenProvider;

private final BlackListService blackListService;

private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
Expand Down

0 comments on commit d01c73f

Please sign in to comment.