Spring Data Redis 사용, Refresh token, Access token

보트·2023년 8월 8일
0

Redis

목록 보기
1/2

Redis

설치

설치 후
-> 작업 관리자 > 서비스 탭에서 확인 가능
만약 실행되지 않았다면
-> 설치경로 > redis-server.exe 파일 수동 실행

redis-cli.exe 통해 명령어 사용
(참고 : https://inpa.tistory.com/entry/REDIS-%F0%9F%93%9A-%EA%B0%9C%EB%85%90-%EC%86%8C%EA%B0%9C-%EC%82%AC%EC%9A%A9%EC%B2%98-%EC%BA%90%EC%8B%9C-%EC%84%B8%EC%85%98-%ED%95%9C%EB%88%88%EC%97%90-%EC%8F%99-%EC%A0%95%EB%A6%AC?category=918728)
(참고 : https://inpa.tistory.com/entry/REDIS-%F0%9F%93%9A-Window10-%ED%99%98%EA%B2%BD%EC%97%90-Redis-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0)
(설치 : https://github.com/microsoftarchive/redis/releases)

Spring 로그인

(참고 : https://wildeveloperetrain.tistory.com/57)

Redis 추가

RedisConfig.java 생성

@Configuration
public class RedisConfig {

    @Value("${redis.host}")
    private String redisHost;

    @Value("${redis.port}")
    private int redisPort;

    // Redis 저장소와 연결
    @Bean
    public RedisConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory(redisHost, redisPort);
    }

    /***
     * Redis 서버와 통신
     * StringRedisTemplate를 사용하여 Key, value를 모두 문자열로 저장
     */
    @Bean
    public StringRedisTemplate redisTemplate() {
        final StringRedisTemplate redisTemplate = new StringRedisTemplate();

        // RedisTemplate을 사용할 때 Spring-Redis 간 데이터 직렬화/역직렬화 시 사용하는 방식이 jdk 직렬화 방식
        // 동작에는 문제가 없지만 redis-cli를 통해 데이터를 확인할 때 알아볼 수 없는 형태로 출력되기 때문
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());

        redisTemplate.setConnectionFactory(connectionFactory());
        return redisTemplate;
    }
}

(참고 : https://wildeveloperetrain.tistory.com/59)

@Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String accessToken = jwtUtil.getJwtFromCookie(request);

        if (StringUtils.hasText(accessToken)) {
            accessToken = jwtUtil.substringToken(accessToken);
            log.info("액세스 토큰 값 : " + accessToken);

			<<시도 2. 요청을 받을 때마다 새로운 토큰 발급>>
            
            if (!jwtUtil.validateToken(accessToken)) {
                log.info("액세스 토큰 유효하지 않음");
                
                <<시도 1. 만료됐다면 새로운 토큰 발급>>
                
				return;
            }

            log.info("body의 사용자 정보 꺼내기");
            Claims info = jwtUtil.getUserInfoFromToken(accessToken);

            try {
                // token 생성 시 subject에 username 넣어둠
                log.info(info.getSubject());
                setAuthentication(info.getSubject());
            } catch (Exception e) {
                return;
            }
        }

        filterChain.doFilter(request, response);
    }

문제

시도

  1. 토큰이 만료됐다면 새로운 access token 발급

-> 요청을 2번 보내야 원하는 작업 할 수 있음
(1번 : 새로운 토큰 발급/ 2번 : 새로운 토큰으로 작업)

  1. 요청이 들어올 때마다 새로운 access token 발급
    (1.의 문제 해결)

JwtAuthorizationFilter.java의 doFilterInternal

 @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String accessToken = jwtUtil.getJwtFromCookie(request);

        if (StringUtils.hasText(accessToken)) {
            accessToken = jwtUtil.substringToken(accessToken);
            log.info("액세스 토큰 값 : " + accessToken);

            String newAccessToken = jwtUtil.reissueAccessToken(accessToken);
            if (newAccessToken != null) {
                jwtUtil.addJwtToCookie(newAccessToken, response);
            }

            if (!jwtUtil.validateToken(accessToken)) {
                log.info("액세스 토큰 유효하지 않음");
                return;
            }

            log.info("body의 사용자 정보 꺼내기");
            Claims info = jwtUtil.getUserInfoFromToken(accessToken);

            try {
                // token 생성 시 subject에 username 넣어둠
                log.info(info.getSubject());
                setAuthentication(info.getSubject());
            } catch (Exception e) {
                log.info("오류 발생");
                return;
            }
        }
        filterChain.doFilter(request, response);
    }
profile
일주일에 한 번

0개의 댓글