본문 바로가기
프로젝트

꾸똑(구독을 똑똑하게) - Security(Redis & Session)

by jucheol 2025. 1. 15.

이번 프로젝트에서 spring security를 사용하여 session을 redis에 저장하는 방식으로 진행하기로 했다.

 

security config

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers(
                                "/swagger", "/swagger-ui.html", "/swagger-ui/**",
                                "/api-docs", "/api-docs/**", "/v3/api-docs/**",
                                "/api/users/signup", "/api/users/signin"
                        ).permitAll()
                        .anyRequest().authenticated()
                )
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED));
        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
}

 

sessionManagement() 설정은 애플리케이션의 세션 생성 및 관리 방식을 제어한다.

sessionCreationPolicy는 세션 생성 정책을 결정하며, 다음 네 가지 옵션 중  IF_REQUIRED을 사용하였다.

 

sessionCreationPolicy의 옵션 설명

1. IF_REQUIRED (기본값)

설명:

  • 요청에 인증이 필요한 경우에만 세션을 생성한다
  • 인증이 필요하지 않거나 기존 세션이 없을 때는 새로운 세션을 생성하지 않는다

동작:

  • 인증이 필요한 요청이 들어오면 세션 생성.
  • 세션이 이미 존재하면 기존 세션을 사용.
  • 인증이 필요하지 않으면 세션을 생성하지 않음.

2. ALWAYS

설명:

  • 요청마다 항상 세션을 생성한다
  • 기존 세션이 있으면 재사용하고, 없으면 새로 생성한다

동작:

  • 요청 시 항상 세션을 생성.
  • 인증 여부와 상관없이 세션을 강제 생성.

3. NEVER

설명:

  • Spring Security가 세션을 생성하지 않는다
  • 다만, 이미 존재하는 세션이 있다면 이를 사용한다

동작:

  • 기존 세션이 있으면 사용.
  • 새로운 세션은 생성하지 않음.

4. STATELESS

설명:

  • 세션을 전혀 사용하지 않는다
  • 인증 정보는 항상 요청과 함께 전송되어야 한다(예: JWT 기반 인증).

동작:

  • 세션을 생성하지 않음.
  • 기존 세션이 있어도 사용하지 않음.
  • 클라이언트가 요청마다 인증 정보를 포함해야 함(JWT, OAuth 등).

redis config

@Configuration
@EnableRedisHttpSession(
        maxInactiveIntervalInSeconds = 1800,
        redisNamespace = "GUTTOK_SESSION"
)
public class RedisConfig {

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

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

    @Value("${spring.data.redis.password}")
    private String redisPassword;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
        config.setHostName(redisHost);
        config.setPort(redisPort);
        config.setPassword(redisPassword);
        return new LettuceConnectionFactory(config);
    }
}

 

maxInactiveIntervalInSeconds = 1800

maxInactiveIntervalInSeconds를 통하여 session이 만료되는 시간을 설정해 줬다.

 

처음에는 3600(1시간)으로 시간을 설정했었다.

1시간이면 너무 긴 시간을 준것 같아서 보통 프로젝트의 보안을 위해 session이 만료되는 시간을 찾아보니 보안이 민감한 프로젝트에서는 1800(30분)보다 짧은 시간을 사용하고, 민감하지 않은 프로젝트에서는 3600도 사용한다고 한다.

위 내용을 고려하여 생각해보니 1800이 적당한 시간 같아서 1800으로 설정해 줬다.

redisNamespace = "GUTTOK_SESSION"

redisNameSpace는 redis key의 이름을 GUTTOK_SESSION 으로 설정하기 위해 사용했다.

 

key 이름 수정 전

 

key 이름 수정 후

 

docker-compose에서 redis 값 확인하기

docker exec -it my_redis redis-cli
auth redis비밀번호

 

keys *

지금 redis에 있는 모든 key를 조회한다

ttl 키이름

 

  • 양수: 키의 남은 생존 시간(초 단위).
  • 0: 키가 만료된 상태 (즉시 삭제될 예정).
  • -1: 키가 만료되지 않음 (영구적으로 저장됨).
  • -2: 키가 존재하지 않음.

1800에서 1714의 시간이 남았다