아장아장 개발 일기

Spring JSESSIONID를 통한 유저 구분 및 테스트 코드 본문

개발/Spring

Spring JSESSIONID를 통한 유저 구분 및 테스트 코드

빨간머리 마녀 🍒 2022. 11. 30. 16:06

구현 배경 및 목적

최근에 별도의 회원가입과 로그인없이 없는 프로젝트를 개발하게 되었다.

 

기존에 사용하던 로직과는 다르게 사용자를 Spring의 JSESSIONID로만 구분하여 GuestUser로 저장, 활용했다.

(데모 수준의 서비스라 일정 시간동안만 저장한 데이터가 쌓이면 되고, 해당 데이터를 지속적으로 관리할 필요가 없었다.)

 

JSESSIONID를 활용한 접속 데이터 구분 및 활용은 아래의 세가지 로직을 따른다. 

  1. Spring의 SecurityContextHolder에서는 Anonymous User를 기본적으로 생성한다.(JSESSIONID 포함)
  2. 이렇게 생성된 SecurityContextHolder의 JSESSIONID를 활용하여, 접속자 정보를 GuestUser 테이블에 저장한다.
  3. api 호출시, 같이 전달되는 JSESSIONID를 활용해 GuestUser 테이블에서 조회한다.

       

 

→ 이를 통해 로그인 없이도 접속한 유저별로 구분하여 REST API 호출이 가능하다.

 

구현 소스

WebSecurityConfig

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig {
    private final GuestUserRepository guestUserRepository;
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/test1", "/test3").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .addFilterBefore(new CustomAuthenticationFilter(guestUserRepository), UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
}

Authentication 시 작동하는 Filter

@RequiredArgsConstructor
public class CustomAuthenticationFilter extends GenericFilterBean {

    private final GuestUserRepository guestUserRepository;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String sessionId = httpServletRequest.getSession().getId();

        GuestUser guestUser = guestUserRepository.findBySessionId(sessionId).orElse(null);
        if (guestUser == null)
            guestUserRepository.save(new GuestUser(sessionId));

        chain.doFilter(request, response);
    }
}

GuestUser Entity

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GuestUser {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    Long id;

    String sessionId;

    @CreationTimestamp
    LocalDateTime createdAt;

    @UpdateTimestamp
    LocalDateTime updatedAt;

    public GuestUser(String sessionId) {
        this.sessionId = sessionId;
    }

}

application.properties

#3시간 접속 없으면 세션 clear
server.servlet.session.timeout=10800

참고

[Spring] session으로 로그인 유지하기

 

Spring Session 다루기 : 세션 정보, 세션 타임 아웃 설정

Comments