Generate Refresh token && save to Redis
This commit is contained in:
@@ -9,7 +9,10 @@ import demo.api.auth.dtos.SignInReq;
|
||||
import demo.api.auth.dtos.SignUpReq;
|
||||
import demo.api.user.repository.UserRepository;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -28,6 +31,10 @@ public class AuthServiceImpl implements AuthService {
|
||||
private final PasswordEncoder bCryptPasswordEncoder;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
@Value("${jwt.token.refresh-token-expire-length}")
|
||||
private long refresh_token_expire_time;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@@ -56,7 +63,21 @@ public class AuthServiceImpl implements AuthService {
|
||||
signInReq.getPassword()
|
||||
)
|
||||
);
|
||||
TokenDto tokenDto = new TokenDto(jwtTokenProvider.generateToken(authentication));
|
||||
|
||||
String refresh_token = jwtTokenProvider.generateRefreshToken(authentication);
|
||||
|
||||
TokenDto tokenDto = new TokenDto(
|
||||
jwtTokenProvider.generateAccessToken(authentication),
|
||||
refresh_token
|
||||
);
|
||||
|
||||
// Redis에 저장 - 만료 시간 설정을 통해 자동 삭제 처리
|
||||
redisTemplate.opsForValue().set(
|
||||
authentication.getName(),
|
||||
refresh_token,
|
||||
refresh_token_expire_time,
|
||||
TimeUnit.MILLISECONDS
|
||||
);
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.add("Authorization", "Bearer " + tokenDto.getAccess_token());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package demo.api.config;
|
||||
|
||||
import demo.api.user.domain.User;
|
||||
import demo.api.user.exception.UserNotFoundException;
|
||||
import demo.api.exception.UserNotFoundException;
|
||||
import demo.api.user.repository.UserRepository;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package demo.api.user.exception;
|
||||
package demo.api.exception;
|
||||
|
||||
public class UserNotFoundException extends RuntimeException {
|
||||
public UserNotFoundException() {
|
||||
@@ -26,7 +26,7 @@ public class JwtTokenFilter extends OncePerRequestFilter {
|
||||
) throws ServletException, IOException {
|
||||
String token = jwtTokenProvider.resolveToken(request);
|
||||
try {
|
||||
if (token != null && jwtTokenProvider.validateToken(token)) {
|
||||
if (token != null && jwtTokenProvider.validateAccessToken(token)) {
|
||||
Authentication auth = jwtTokenProvider.getAuthentication(token);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth); // 정상 토큰이면 SecurityContext에 저장
|
||||
}
|
||||
|
||||
@@ -19,33 +19,57 @@ import org.springframework.stereotype.Component;
|
||||
// 유저 정보로 JWT 토큰을 만들거나 토큰을 바탕으로 유저 정보를 가져옴
|
||||
@Component
|
||||
public class JwtTokenProvider {
|
||||
@Value("${jwt.token.secret-key}")
|
||||
private String secret_key;
|
||||
@Value("${jwt.token.access-token-secret-key}")
|
||||
private String access_token_secret_key;
|
||||
|
||||
@Value("${jwt.token.expire-length}")
|
||||
private long expire_time;
|
||||
@Value("${jwt.token.refresh-token-secret-key}")
|
||||
private String refresh_token_secret_key;
|
||||
|
||||
@Value("${jwt.token.access-token-expire-length}")
|
||||
private long access_token_expire_time;
|
||||
|
||||
@Value("${jwt.token.refresh-token-expire-length}")
|
||||
private long refresh_token_expire_time;
|
||||
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
/**
|
||||
* 적절한 설정을 통해 토큰을 생성하여 반환
|
||||
* 적절한 설정을 통해 Access 토큰을 생성하여 반환
|
||||
* @param authentication
|
||||
* @return
|
||||
* @return access token
|
||||
*/
|
||||
public String generateToken(Authentication authentication) {
|
||||
|
||||
public String generateAccessToken(Authentication authentication) {
|
||||
Claims claims = Jwts.claims().setSubject(authentication.getName());
|
||||
// claims.put("auth", appUserRoles.stream().map(s -> new SimpleGrantedAuthority(s.getAuthority())).filter(Objects::nonNull).collect(Collectors.toList()));
|
||||
|
||||
Date now = new Date();
|
||||
Date expiresIn = new Date(now.getTime() + expire_time);
|
||||
Date expiresIn = new Date(now.getTime() + access_token_expire_time);
|
||||
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.setIssuedAt(now)
|
||||
.setExpiration(expiresIn)
|
||||
.signWith(SignatureAlgorithm.HS256, secret_key)
|
||||
.signWith(SignatureAlgorithm.HS256, access_token_secret_key)
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 적절한 설정을 통해 Refresh 토큰을 생성하여 반환
|
||||
* @param authentication
|
||||
* @return refresh token
|
||||
*/
|
||||
public String generateRefreshToken(Authentication authentication) {
|
||||
Claims claims = Jwts.claims().setSubject(authentication.getName());
|
||||
|
||||
Date now = new Date();
|
||||
Date expiresIn = new Date(now.getTime() + refresh_token_expire_time);
|
||||
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.setIssuedAt(now)
|
||||
.setExpiration(expiresIn)
|
||||
.signWith(SignatureAlgorithm.HS256, refresh_token_secret_key)
|
||||
.compact();
|
||||
}
|
||||
|
||||
@@ -55,7 +79,7 @@ public class JwtTokenProvider {
|
||||
* @return
|
||||
*/
|
||||
public Authentication getAuthentication(String token) {
|
||||
String username = Jwts.parser().setSigningKey(secret_key).parseClaimsJws(token).getBody().getSubject();
|
||||
String username = Jwts.parser().setSigningKey(access_token_secret_key).parseClaimsJws(token).getBody().getSubject();
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||
|
||||
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
|
||||
@@ -75,17 +99,32 @@ public class JwtTokenProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* 토큰을 검증
|
||||
* Access 토큰을 검증
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public boolean validateToken(String token) {
|
||||
public boolean validateAccessToken(String token) {
|
||||
try {
|
||||
Jwts.parser().setSigningKey(secret_key).parseClaimsJws(token);
|
||||
Jwts.parser().setSigningKey(access_token_secret_key).parseClaimsJws(token);
|
||||
return true;
|
||||
} catch (JwtException e) {
|
||||
// MalformedJwtException | ExpiredJwtException | IllegalArgumentException
|
||||
throw new CustomException("Error on Token", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
throw new CustomException("Error on Access Token", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh 토큰을 검증
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public boolean validateRefreshToken(String token) {
|
||||
try {
|
||||
Jwts.parser().setSigningKey(refresh_token_secret_key).parseClaimsJws(token);
|
||||
return true;
|
||||
} catch (JwtException e) {
|
||||
// MalformedJwtException | ExpiredJwtException | IllegalArgumentException
|
||||
throw new CustomException("Error on Refresh Token", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
package demo.api.user;
|
||||
|
||||
import demo.api.user.domain.User;
|
||||
import demo.api.user.dtos.ProfileDto.ProfileReq;
|
||||
import demo.api.user.dtos.ProfileDto.ProfileRes;
|
||||
import demo.api.user.exception.UserNotFoundException;
|
||||
import demo.api.exception.UserNotFoundException;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
Reference in New Issue
Block a user