SPRING

[Springboot] JWT(6) _ 로그아웃 구현/AccessToken 블랙리스트 + RefreshToken 삭제 + Redis

체제 2022. 8. 24. 00:09

사용자가 로그인 하면, accessToken 과 refreshToken 을 발급하여 응답하였고, 서버에서는 refreshToken 을 사용자 아이디와 함께 Redis 에 저장해 두었다. 

사용자가 로그아웃 요청을 하게 되면, accessToken 의 남은 시간을 계산 하여 redis 에 블랙리스트로 저장하였고, refreshToken 은 레디스에서 삭제하였다.


AuthController.java - 로그아웃처리 컨트롤러, 레디스에 저장 및 삭제만 하면 되기때문에 컨트롤러에서 처리하였음 

@PostMapping("/logout")
	public String  userLogout(@RequestBody UserLogoutRequest logoutInfo) throws Exception{
		// redis 에서 refresh token 값 삭제 
		String token = logoutInfo.getAccessToken();
		try{
			JwtTokenUtil.handleError(token);
		}catch(ExpiredJwtException e) {
			log.debug("토큰만료");
			throw new JwtException("토큰기한이 만료되었습니다.");
		}catch(Exception e) {
			log.debug("토큰 x");
			throw new Exception("올바르지 않은 토큰 입니다.");
		}
        
		String id = jwtTokenUtil.getAuth(token);
		//redis에서 해당 아이디로 저장된 value 값이 있는지 검사 
		if(redis.getValues(id) !=null) {
			//redis 토큰 삭제 
			redis.deleteValues(id);
		}
		Long expiration = jwtTokenUtil.getExpiration(token);
		redis.setValues("logout",token, Duration.ofMillis(expiration));
		return "success";
		
	}

▶ accessToken 유효기간이나 토큰 형태를 확인 한 후 , 이상이 있다면 예외처리 

올바른 값이라면, 아이디(getAuth)를 가지고 redis 에 해당 refreshToken 값이 있는지 검사 후 , 삭제 ( deleteValues ) 

  •  JwtTokenUtil.java 의 getExpiration (token) 로 해당 엑세스 토큰의 남은 기간을 확인한 후, redis 에 저장 
  •  → 해당 기간이 지나면 redis 에서 자동으로 삭제

 

 

 


JwtTokenUtil.java 

  • 토큰 값에서 사용자 아이디 불러오기 : getAuth() 
  • 엑세스토큰의 남은 유효기간 계산하기 : getExpiration() 
 public String getAuth(String accessToken) {
	Claims claims = Jwts.parserBuilder().setSigningKey(secretKey.getBytes())
      .build().parseClaimsJws(accessToken)
				.getBody();
	return  claims.getSubject();
	 }
public Long getExpiration(String accessToken) {
	 // accessToken 남은 유효시간
	 Date expiration = Jwts.parserBuilder().setSigningKey(secretKey.getBytes()  
       .build().parseClaimsJws(accessToken).getBody().getExpiration();
	 // 현재 시간
	 Long now = new Date().getTime();
	 return (expiration.getTime() - now);
}

 

 

RedisService.java - 레디스 값 저장, 불러오기, 삭제 등의 메서드를 정의

@Service
@RequiredArgsConstructor
public class RedisService {
	private final RedisTemplate<String, String> redisTemplate;
	
	public void setValues(String key, String data) {
		ValueOperations<String, String> values= redisTemplate.opsForValue();
		values.set(key,data);
	}
	
	public void setValues(String key, String data, Duration duration) {
		ValueOperations<String, String> values= redisTemplate.opsForValue();
		values.set(key,data,duration);
	}
	
	public String getValues(String key) {
		ValueOperations<String, String> values= redisTemplate.opsForValue();
		return values.get(key);
	}
	
	public void deleteValues(String key) {
		redisTemplate.delete(key);
	}

}
  • setValues : key 값으로 data 저장 
  • setValues + duration : key 값으로 data 를 duration 기간 만큼 저장 
  • getValues : key 값을 가진 데이터 불러오기 
  • deleteValues : key 값을 가진 데이터 삭제