feat(user-service): JWT 토큰 관련 로직 변경
- access token 재발급 시 response body에 만료 시간 추가 - 페이지 이동 시 사용할 access token check 로직 추가
This commit is contained in:
@@ -6,6 +6,6 @@ import org.springframework.http.HttpStatus;
|
|||||||
public class AccessTokenNotValidException extends CustomException {
|
public class AccessTokenNotValidException extends CustomException {
|
||||||
|
|
||||||
public AccessTokenNotValidException(String message) {
|
public AccessTokenNotValidException(String message) {
|
||||||
super(HttpStatus.FORBIDDEN, message);
|
super(HttpStatus.UNAUTHORIZED, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.justpickup.userservice.domain.jwt.service;
|
||||||
|
|
||||||
|
public interface AccessTokenService {
|
||||||
|
|
||||||
|
void checkAccessToken(String authorizationHeader);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.justpickup.userservice.domain.jwt.service;
|
||||||
|
|
||||||
|
import com.justpickup.userservice.domain.jwt.exception.AccessTokenNotValidException;
|
||||||
|
import com.justpickup.userservice.global.utils.JwtTokenProvider;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AccessTokenServiceImpl implements AccessTokenService {
|
||||||
|
|
||||||
|
private final JwtTokenProvider tokenProvider;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkAccessToken(String authorizationHeader) {
|
||||||
|
|
||||||
|
String token = authorizationHeader.replace("Bearer", "");
|
||||||
|
|
||||||
|
if (!tokenProvider.validateJwtToken(token)) {
|
||||||
|
throw new AccessTokenNotValidException("Access Token is not Valid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -69,9 +70,11 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
|
|||||||
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
|
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
|
||||||
|
|
||||||
String newAccessToken = jwtTokenProvider.createJwtAccessToken(userId, "/refreshToken", roles);
|
String newAccessToken = jwtTokenProvider.createJwtAccessToken(userId, "/refreshToken", roles);
|
||||||
|
Date expiredTime = jwtTokenProvider.getExpiredTime(newAccessToken);
|
||||||
|
|
||||||
return JwtTokenDto.builder()
|
return JwtTokenDto.builder()
|
||||||
.accessToken(newAccessToken)
|
.accessToken(newAccessToken)
|
||||||
|
.accessTokenExpiredDate(expiredTime)
|
||||||
.refreshToken(refreshToken)
|
.refreshToken(refreshToken)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.justpickup.userservice.domain.jwt.web;
|
package com.justpickup.userservice.domain.jwt.web;
|
||||||
|
|
||||||
import com.justpickup.userservice.domain.jwt.service.RefreshTokenServiceImpl;
|
import com.justpickup.userservice.domain.jwt.service.AccessTokenService;
|
||||||
|
import com.justpickup.userservice.domain.jwt.service.RefreshTokenService;
|
||||||
import com.justpickup.userservice.domain.user.dto.JwtTokenDto;
|
import com.justpickup.userservice.domain.user.dto.JwtTokenDto;
|
||||||
import com.justpickup.userservice.global.dto.Result;
|
import com.justpickup.userservice.global.dto.Result;
|
||||||
import com.justpickup.userservice.global.utils.CookieProvider;
|
import com.justpickup.userservice.global.utils.CookieProvider;
|
||||||
@@ -15,20 +16,22 @@ import org.springframework.http.ResponseEntity;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/auth")
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class AuthController {
|
public class AuthController {
|
||||||
|
|
||||||
private final RefreshTokenServiceImpl refreshTokenServiceImpl;
|
private final RefreshTokenService refreshTokenService;
|
||||||
|
private final AccessTokenService accessTokenService;
|
||||||
private final CookieProvider cookieProvider;
|
private final CookieProvider cookieProvider;
|
||||||
|
|
||||||
@GetMapping("/refreshToken")
|
@GetMapping("/reissue")
|
||||||
public ResponseEntity<Result> refreshToken(@RequestHeader("X-AUTH-TOKEN") String accessToken,
|
public ResponseEntity<Result> refreshToken(@RequestHeader("X-AUTH-TOKEN") String accessToken,
|
||||||
@CookieValue("refresh-token") String refreshToken) {
|
@CookieValue("refresh-token") String refreshToken) {
|
||||||
|
JwtTokenDto jwtTokenDto = refreshTokenService.refreshJwtToken(accessToken, refreshToken);
|
||||||
JwtTokenDto jwtTokenDto = refreshTokenServiceImpl.refreshJwtToken(accessToken, refreshToken);
|
|
||||||
|
|
||||||
ResponseCookie responseCookie = cookieProvider.createRefreshTokenCookie(refreshToken);
|
ResponseCookie responseCookie = cookieProvider.createRefreshTokenCookie(refreshToken);
|
||||||
|
|
||||||
@@ -42,9 +45,12 @@ public class AuthController {
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
static class RefreshTokenResponse {
|
static class RefreshTokenResponse {
|
||||||
private String accessToken;
|
private String accessToken;
|
||||||
|
private String expiredTime;
|
||||||
|
|
||||||
public RefreshTokenResponse(JwtTokenDto jwtTokenDto) {
|
public RefreshTokenResponse(JwtTokenDto jwtTokenDto) {
|
||||||
this.accessToken = jwtTokenDto.getAccessToken();
|
this.accessToken = jwtTokenDto.getAccessToken();
|
||||||
|
this.expiredTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||||
|
.format(jwtTokenDto.getAccessTokenExpiredDate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +58,7 @@ public class AuthController {
|
|||||||
public ResponseEntity<Result> logout(@RequestHeader("X-AUTH-TOKEN") String accessToken,
|
public ResponseEntity<Result> logout(@RequestHeader("X-AUTH-TOKEN") String accessToken,
|
||||||
@RequestHeader("REFRESH-TOKEN") String refreshToken) {
|
@RequestHeader("REFRESH-TOKEN") String refreshToken) {
|
||||||
|
|
||||||
refreshTokenServiceImpl.logoutToken(accessToken);
|
refreshTokenService.logoutToken(accessToken);
|
||||||
|
|
||||||
ResponseCookie refreshCookie = cookieProvider.removeRefreshTokenCookie();
|
ResponseCookie refreshCookie = cookieProvider.removeRefreshTokenCookie();
|
||||||
|
|
||||||
@@ -60,4 +66,13 @@ public class AuthController {
|
|||||||
.header(HttpHeaders.SET_COOKIE, refreshCookie.toString())
|
.header(HttpHeaders.SET_COOKIE, refreshCookie.toString())
|
||||||
.body(Result.createErrorResult(""));
|
.body(Result.createErrorResult(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/check/access-token")
|
||||||
|
public ResponseEntity<Result> checkAccessToken(@RequestHeader(name = "Authorization") String authorization) {
|
||||||
|
|
||||||
|
accessTokenService.checkAccessToken(authorization);
|
||||||
|
|
||||||
|
return ResponseEntity.status(HttpStatus.OK)
|
||||||
|
.body(Result.createSuccessResult(null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,18 @@ package com.justpickup.userservice.domain.user.dto;
|
|||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class JwtTokenDto {
|
public class JwtTokenDto {
|
||||||
private String accessToken;
|
private String accessToken;
|
||||||
|
private Date accessTokenExpiredDate;
|
||||||
private String refreshToken;
|
private String refreshToken;
|
||||||
|
|
||||||
@Builder
|
@Builder
|
||||||
public JwtTokenDto(String accessToken, String refreshToken) {
|
public JwtTokenDto(String accessToken, String refreshToken, Date accessTokenExpiredDate) {
|
||||||
this.accessToken = accessToken;
|
this.accessToken = accessToken;
|
||||||
this.refreshToken = refreshToken;
|
this.refreshToken = refreshToken;
|
||||||
|
this.accessTokenExpiredDate = accessTokenExpiredDate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class GlobalExceptionHandler {
|
|||||||
// 쿠키 삭제
|
// 쿠키 삭제
|
||||||
ResponseCookie responseCookie = cookieProvider.removeRefreshTokenCookie();
|
ResponseCookie responseCookie = cookieProvider.removeRefreshTokenCookie();
|
||||||
|
|
||||||
return ResponseEntity.status(HttpStatus.FORBIDDEN)
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
|
||||||
.header(HttpHeaders.SET_COOKIE, responseCookie.toString())
|
.header(HttpHeaders.SET_COOKIE, responseCookie.toString())
|
||||||
.body(e.getResult());
|
.body(e.getResult());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,12 @@ import org.springframework.security.core.userdetails.User;
|
|||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -70,6 +71,7 @@ public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFil
|
|||||||
String userId = user.getUsername();
|
String userId = user.getUsername();
|
||||||
|
|
||||||
String accessToken = jwtTokenProvider.createJwtAccessToken(userId, request.getRequestURI(), roles);
|
String accessToken = jwtTokenProvider.createJwtAccessToken(userId, request.getRequestURI(), roles);
|
||||||
|
Date expiredTime = jwtTokenProvider.getExpiredTime(accessToken);
|
||||||
String refreshToken = jwtTokenProvider.createJwtRefreshToken();
|
String refreshToken = jwtTokenProvider.createJwtRefreshToken();
|
||||||
|
|
||||||
refreshTokenServiceImpl.updateRefreshToken(Long.valueOf(userId), jwtTokenProvider.getRefreshTokenId(refreshToken));
|
refreshTokenServiceImpl.updateRefreshToken(Long.valueOf(userId), jwtTokenProvider.getRefreshTokenId(refreshToken));
|
||||||
@@ -83,17 +85,11 @@ public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFil
|
|||||||
response.addCookie(cookie);
|
response.addCookie(cookie);
|
||||||
|
|
||||||
// body 설정
|
// body 설정
|
||||||
Map<String, String> tokens = Map.of(
|
Map<String, Object> tokens = Map.of(
|
||||||
"access_token", accessToken
|
"accessToken", accessToken,
|
||||||
|
"expiredTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(expiredTime)
|
||||||
);
|
);
|
||||||
|
|
||||||
new ObjectMapper().writeValue(response.getOutputStream(), Result.createSuccessResult(tokens));
|
new ObjectMapper().writeValue(response.getOutputStream(), Result.createSuccessResult(tokens));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void unsuccessfulAuthentication
|
|
||||||
(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)
|
|
||||||
throws IOException, ServletException {
|
|
||||||
log.warn("로그인 실패!!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,6 @@ import io.jsonwebtoken.*;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -57,8 +53,6 @@ public class JwtTokenProvider {
|
|||||||
.compact();
|
.compact();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getUserId(String token) {
|
public String getUserId(String token) {
|
||||||
return getClaimsFromJwtToken(token).getSubject();
|
return getClaimsFromJwtToken(token).getSubject();
|
||||||
}
|
}
|
||||||
@@ -75,6 +69,10 @@ public class JwtTokenProvider {
|
|||||||
return getClaimsFromJwtToken(token).get("value").toString();
|
return getClaimsFromJwtToken(token).get("value").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Date getExpiredTime(String token) {
|
||||||
|
return getClaimsFromJwtToken(token).getExpiration();
|
||||||
|
}
|
||||||
|
|
||||||
public List<String> getRoles(String token) {
|
public List<String> getRoles(String token) {
|
||||||
return (List<String>) getClaimsFromJwtToken(token).get("roles");
|
return (List<String>) getClaimsFromJwtToken(token).get("roles");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user