용어정리 

Authentication : 사용자 정보가 담긴 데이터 객체

SecurityContext : Authentication 을 담는 보관함 

SecurityContextHolder : 현재 실행중인 스레드 관리자

HttpSession : 브라우저 종료 전까지 서버 메모리에 유지되는 저장소

 

로그인 성공 시 흐름

1. loadUserByUsername 를 통해 가져온 사용자 정보의 인증이 성공하면 Authentication 객체 생성

2. 생성된 Authentication 객체를 SecurityContext에 넣고 SecurityContextHolder 를 통해 현재 작업환경에 등록

3. Spring Security가 SecurityContext를 HttpSession에 저장, 쿠키 발급

 

페이지 이동 시 흐름

1. 다른 페이지 이동 시 가지고 있던 쿠키를 서버로 전송

2. 쿠키를 보고 HttpSession에 SecurityContext이 있는지 확인 후 다시 SecurityContextHolder 에 등록

 

세션 관리 설정

application.properties에

# 세션 유지 시간 설정(30분)
server.servlet.session.timeout=30m   

를 추가하여 세션 유지 시간을 설정할 수 있다.

 

SecurityConfig 세션관련 설정

http	
    .sessionManagement(session -> session
        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) // 세션 생성 전략
        .maximumSessions(1) // 동시 접속 허용 개수 (1이면 중복 로그인 방지)
        .maxSessionsPreventsLogin(false) // true: 신규 로그인 차단, false: 기존 세션 만료
        .expiredUrl("/login?expired=true") // 세션이 만료되었을 때 이동될 페이지
    );
return http.build();

 

세션 생성 전략 (sessionCreationPolicy)

Spring Security가 세션을 언제 만들지 결정한다.

  • ALWAYS: 항상 생성
  • IF_REQUIRED: 필요할 때만 생성 (기본값, 가장 많이 씀)
  • NEVER: 직접 생성하진 않지만 있으면 사용
  • STATELESS: 세션을 전혀 생성하지 않고 사용하지 않음 (JWT 방식에서 사용)

중복로그인 체크 시 로그인한 사용자 정보를 서로 비교하여 같은 사람인지를 판단해야 하지만, 기본적으로는 판단근거가 부족하다.

실제 유저 정보를 가지고있는 UserDetails의 구현체에서 @EqualsAndHashCode(of "id") 의 형식으로 어떤 필드값을 통해 동일인인지 비교하는 로직을 추가해야한다.

 

 

만약 UserDetails 구현체에서 필드값을 받지 않고 user 객체로 받아서 처리하고 있다면 @EqualsAndHashCode(of = "user") 로도 처리가 가능하다. 이러한 경우 엔티티에서 어떤 값을 통해 비교할지 필드명으로 한번 더 제어를 해야한다.

@EqualsAndHashCode(of = "id")
public class User {
    @Id
    @GeneratedValue //AutoIncrement
    @Column
    private Long id;
@EqualsAndHashCode(of = "user")
public class CustomUserLogin implements UserDetails {

    private final User user;

 

Spring Security는 기본적으로 세션 고정 공격을 방어하기 위해 

로그인이 성공하면 기존의 세션을 버리고 신규 세션을 생성하여 브라우저에 새 쿠키를 할당하도록 되어있다.

(http.sessionFixation().changeSessionId())

 

+ Recent posts