728x90
1. redis 설치
2. gradle에 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
3. application.properties 추가
spring.data.redis.database=0
spring.data.redis.host=localhost
spring.data.redis.port=6379
4. RedisConfig.class 추가
@Configuration
public class RedisConfig {
@Value("${spring.data.redis.host}")
private String host;
@Value("${spring.data.redis.port}")
private int port;
// password는 사용 시 추가
// @Value("${spring.data.redis.password}")
// private int password;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
redisConfiguration.setHostName(host);
redisConfiguration.setPort(port);
// redisConfiguration.setPassword(String.valueOf(password));
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisConfiguration);
return lettuceConnectionFactory;
}
@Primary
@Bean
// 트랜잭션 지원. 하나의 로직이 실패하여 오류가 나는 경우 수행한 작업을 모두 취소
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
}
4. RedisService 추가
@Service
@RequiredArgsConstructor
public class RedisService {
private final RedisTemplate redisTemplate;
@Transactional
public void setRefreshToken(RefreshToken refreshToken){
ValueOperations<String, String> values = redisTemplate.opsForValue();
values.set(refreshToken.getRefreshToken(), String.valueOf(refreshToken.getUserid()));
redisTemplate.expire(String.valueOf(refreshToken.getUserid()), (60 * 60 * 24 * 14 + 60), TimeUnit.SECONDS);
}
public String getRefreshToken(String refreshToken){
ValueOperations<String, String> values = redisTemplate.opsForValue();
return values.get(refreshToken);
}
public String getRefreshToken(Long userId) {
ValueOperations<String, String> values = redisTemplate.opsForValue();
Set<String> keys = redisTemplate.keys("*");
for (String key : keys) {
String value = values.get(key);
if (value != null && Long.parseLong(value) == userId) {
return key;
}
}
return null;
}
}
5. JwtAuthenticationFilter에 아래의 코드 추가
@Override
public void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException {
String username = ((UserDetailsImpl) authResult.getPrincipal()).getUsername();
UserRoleEnum role = ((UserDetailsImpl) authResult.getPrincipal()).getUser().getRole();
Long userId = ((UserDetailsImpl) authResult.getPrincipal()).getUser().getUserId();
// 엑세스 토큰 헤더에 추가
String accessToken = jwtUtil.createAccessToken(username, role);
response.addHeader(JwtUtil.ACCESS_TOKEN, accessToken);
// 리프레시 토큰 헤더에 추가
String refreshToken = jwtUtil.createRefreshToken(username);
response.addHeader(JwtUtil.REFRESH_TOKEN, refreshToken);
// redis에 저장(중복저장 방지를 위한 if문)
if(redisService.getRefreshToken(userId) == null) {
redisService.setRefreshToken(new RefreshToken(refreshToken, userId));
}
response.setStatus(200);
new ObjectMapper().writeValue(response.getOutputStream(), new ResultResponseDto("로그인 성공"));
}
6. 토큰 만료시 client가 리프레시 토큰을 가지고 있다면 엑세스 토큰 재발급
try {
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
...
} catch (ExpiredJwtException e) {
if(req.getHeader(REFRESH_TOKEN).isEmpty()) {
log.error("Expired JWT token, 만료된 JWT token 입니다.");
throw new RuntimeException();
} else if("redis의 리프레시 토큰과 header의 리프레시 토큰 간 검증") {
String RefreshToken = req.getHeader(REFRESH_TOKEN);
String newAccessToken = regenerateAccessToken(RefreshToken);
res.addHeader(JwtUtil.ACCESS_TOKEN, newAccessToken);
res.addHeader(JwtUtil.REFRESH_TOKEN, RefreshToken);
log.info("토큰재발급 성공: {}", newAccessToken);
}
...
'Springboot' 카테고리의 다른 글
[CS] 정규화 및 반정규화 (0) | 2023.07.29 |
---|---|
[springboot] 07-21 ~ 07-27 (0) | 2023.07.27 |
[Springboot] DAO, DTO, VO (0) | 2023.07.18 |
[Springboot] CORS란? (2) | 2023.07.15 |
[Springboot] Handler, @ExceptionHandler, @ControllerAdvice (1) | 2023.07.11 |