Oauth 카카오 로그인 + Spring Boot + JWT 로그인 구현(2)
지난 글에서 Jwt AccessToken, RefreshToken을 발급받는 과정까지 구현해 보았다
- 발행된
AccessToken
의 값은 무조건적으로 명백하다고 생각하여 요청을 허가시킴. Access Token탈취
의 위험이 존재하기 때문에 짧은 유효시간을 두어, Access Token이 탈취 당하더라도만료
되어 사용할 수 없도록 한다. - Refresh Token은 서버에서 그 값
(Redis)
을 저장함. Refresh Token을 사용할 상황이 오면 반드시 서버에서 그유효성
을 판별, 유효하지 않는 경우라면 요청을거부
혹은 사용자로부터 탈취됐다는 정보가 오면 그 Refrsh Token을폐기
할 수 있도록 설정.
위 과정에서 Redis를 사용하는 이유는 다음과 같다.
- Refresh Token을 서버에서 어디에다 저장할 것인가?
이미 정답을 제시하고 문제를 냈기 때문에 답하는데 김이 빠지긴 하지만 이유를 설명하자면 Refresh Token은 만료
되어야 하기 때문이다. 그럼 휘발성을 가진 데이터 베이스가 무엇이 있을까? 정답 : Redis
Redis를 사용하기 위해선 Dependency를 추가해준다.
먼저 Redis는 설치가 되어있다고 가정하고 진행을 하겠습니다.
Redis
Gradle
에 추가하기
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
-
application.yml
spring: redis: host: localhost port: 6379
- 다음과 같이
RedisUtil
클래스를 설정을 해주어야 한다.
@Component
@RequiredArgsConstructor
public class RedisUtil {
private final StringRedisTemplate stringRedisTemplate;
public String getData(String key) {
ValueOperations<String,String> valueOperations = stringRedisTemplate.opsForValue();
return valueOperations.get(key);
}
public void setData(String key, String value) {
ValueOperations<String,String> valueOperations = stringRedisTemplate.opsForValue();
valueOperations.set(key, value);
}
public void setDataExpire(String key, String value, long duration) {
ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
Duration expireDuration = Duration.ofSeconds(duration);
valueOperations.set(key, value, expireDuration);
}
public void deleteData(String key) {
stringRedisTemplate.delete(key);
}
}
먼저 위와 같이 설정을 끝냈다면 이전 게시글에서 작성했던 코드를 바꿔보자
@Component
@RequiredArgsConstructor
public class RedisUtil {
private final StringRedisTemplate stringRedisTemplate;
public String getData(String key) {
ValueOperations<String,String> valueOperations = stringRedisTemplate.opsForValue();
return valueOperations.get(key);
}
public void setData(String key, String value) {
ValueOperations<String,String> valueOperations = stringRedisTemplate.opsForValue();
valueOperations.set(key, value);
}
public void setDataExpire(String key, String value, long duration) {
ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
Duration expireDuration = Duration.ofSeconds(duration);
valueOperations.set(key, value, expireDuration);
}
public void deleteData(String key) {
stringRedisTemplate.delete(key);
}
}
- 자세한 코드는 시간 관계상 넘어가고
Redis
관련 로직만 살펴보겠다. - 먼저 간략하게 설명하자면
Front end
쪽으로 부터Oauth
로그인을 할 때 Oauth 서버로부터 Code를 받아와서 OauthController 에 login을 호출하게 된다. OauthService
의login
메소드를 호출하여 위와 같은 로직이 실행되는데 이전 게시글에서 accessToken의 시간을 30분으로 잡아놨다 그 이유는accessToken
이탈취
당할경우user
의 정보가 그대로 노출이 되기 때문에 accessToken의지속시간
은 되도록짧게
잡아주는 것이 좋다.refreshToke
의 경우 user의 정보가 담겨있는것이 아닌 user의 id만 넣어주기로 했다 refreshToken을 탈취 당하더라도 회원의 정보가 아닌 회원의 아이디만 탈취당하게 된다. refreshToken의 용도는accessToken
의 만료기간이 끝났을 경우재발급
을 받기 위해서 사용된다. 그로인해 accessToken에 비해상대적으로
만료기간을 훨씬길게
잡아주어서 2주일로 설정 하였다.- 이전 게시글에서와 같이 refreshToken을 생성해 주는 것까지는 같다. 여기서 redisUtil.setDataExpire() 메서드로 회원
id, 토큰 값, 토큰 만료 시간'을 넣어서 Redis
에 저장해준다.
실행이 되었다면
Terminal
에서 다음과 같이redis-cli
로 확인을 해보면 된다.
redis-cli
keys * : (redis에 저장된 모든 키
를 보여줌)
get(key) : 입력한 key
에 대한 value
를 보여줌
ttl(key) : 입력한 key
에 대한 만료 시간
을 보여줌
위와 같이 성공적으로 redis
에 값이 들어온 것을 볼 수 있다.
다른 메서드는 아래에서 간략히 보여드리기만 하겠습니다.
- 추가로 redis에 저장된 refreshToken을 사용하는 메서드도 살펴보겠다.
accessToken
재발급
/**
* refresh Token 으로 Access Token 이 만료 되었을 경우 재발급
* Redis Server 에서 refresh Token 을 가져옴
*/
public AccessTokenResponse accessTokenByRefreshToken(String accessToken, RefreshTokenRequest refreshTokenRequest) {
refreshTokenExtractor(refreshTokenRequest);
String id = jwtTokenProvider.getPayload(accessToken);
String data = redisUtil.getData(id);
if (!data.equals(refreshTokenRequest.getRefreshToken())) {
log.info("Exception!!");
throw new CustomException(ErrorCode.UNAUTHORIZED_REFRESH_TOKEN);
}
Token newAccessToken = jwtTokenProvider.createAccessToken(id);
return new AccessTokenResponse(newAccessToken.getValue());
}
로그아웃
/**
* 로그아웃 시 토큰도 같이 삭제
*/
@Transactional
public CustomResponse logout(String accessToken) {
String id = jwtTokenProvider.getPayload(accessToken);
redisUtil.deleteData(id);
return new CustomResponse("로그아웃이 완료 되었습니다.");
}
Author And Source
이 문제에 관하여(Oauth 카카오 로그인 + Spring Boot + JWT 로그인 구현(2)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@do-hoon/Oauth-카카오-로그인-Spring-Boot-JWT-로그인-구현2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)