2022년 5월 24일 TIL

yshjft·2022년 5월 24일
0

데브코스 TIL

목록 보기
38/45

custom UserDetailsService

custom UserDetailsService

@Service
public class UserService implements UserDetailsService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userRepository.findByLoginId(username)
                .map(user ->
                        User.builder()
                                .username(user.getLoginId())
                                .password(user.getPasswd())
                                .authorities(user.getGroup().getAuthorities())
                                .build()
                )
                .orElseThrow(() -> new UsernameNotFoundException("Could not found user for " + username));

    }

}

Spring Security에 Custom UserDetailsService 전달하기

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
     auth.userDetailsService(userService);
}

Custom UserDetailsService을 Bean으로 등록하기만해도 잘 전달된다. 두 방식의 차이는 뭘까? AuthenticationManagerBuilder를 이용하여 Custom UserDetailsService를 등록하였을까?

3-Tier Architecture, HTTP Session 그리고 Session Cluster

3-Tier Architecture

  • 가장 보편적이고 이해하기 쉬운 아키텍처
    • 프레젠테이션 레이어: 사용자와의 접점 제공
    • 애플리케이션 레이어: 트랜잭션 처리를 위한 비즈니스 로직 제공
    • 데이터 레이어: 데이터를 저장하고 조회하는 기능 제공
  • 장점들
    • 프론트엔드, 백엔드 엔지니어 역할 분리에 따른 업무 효율화
    • 각 계층을 모듈화해 다른 계층에 미치는 영향을 최소화하며 확장이 용이하다.

요청이 늘어나면?

  • 서버를 scale out(수평 확장) 해야한다.

늘어난 서버에서 장애가 발생하거나 요청이 줄어들어 서버의 개수가 줄어든다면?

  • 이 때 인증에서 session을 사용했다면?
    • 장애가 발생하거나 사라진 서버의 메모리에 저장된 Session도 같이 사라져 사용자의 인증이 풀리게 된다.

HTTP Session

  • HTTP는 stateless 이다.
  • 서버는 인증된 사용자 정보를 저장하기 위해 Session을 만들고, 식별자인 session-id를 클라이언트로 응답함
    • 클라이언트가 웹 브라우저인 경우 session-id는 보통 Cookie에 저장된다.
  • 클라이언트는 HTTP 요청에 session-id를 포함시켜, 서버가 클라이언트를 식별할 수 있도록 해야함

Session Cluster

  • Session을 별동의 외부 스토리지에 저장한다는 개념이다.
  • 빠른 조회를 위해 In-Memory 데이터베이스를 많이 사용한다.
  • 이를 통해 서버 장애 등의 이유로 인한 세션 유실 문제를 해결할 수 있다.
  • 단 세션을 저장하기 위한 외부 스토리지가 필요한 만큼 관리 포인트가 증가하게 된다. 또한 외부 스토리지에서 장애가 발생할 경우 대규모 장애가 발생할 수 있는 가능성이 커진다.(SPOF)
    • 따라서 외부 스토리지는 보통 클러스터로 구성된다.

Spring Session

  • session 클러스터 구현 쉽게 해준다.
  • 추상화가 되어 있어 실제로 사용하는 스토리지 엔진에 의존하지 않아도 된다.

의존성 추가 및 설정

의존성

<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-jdbc</artifactId>
</dependency>

redis와 같이 다른 종류의 스토리지를 사용하고 싶은 경우 아래와 같이 의존성을 추가한다.

<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-redis</artifactId>
</dependency>

application.yml 설정

session:
    store-type: jdbc

만약 redis를 사용할 거라면 아래와 같이 설정하면 된다.

session:
    store-type: redis

SessionRepository

  • 인터페이스
  • createSession, save, findById, deleteById와 같은 4가지 메서드 지원한다.

구현체

  • MapSessionRepository
    In-Memory Map 기반으로서 별도의 의존 라이브러리가 필요하지 않다.

  • RedisIndexedSessionRepository
    redis 기반이며, @EnableRedisHttpSession 어노테이션으로 생성된다.

  • JdbcIndexedSessionRepository
    jdbc 기반이며, @EnableJdbcHttpSession 어노테이션으로 생성된다.

SessionRepositoryFilter

  • Servlet Filter 중에 하나이다.
    • Spring Security filterchain 보다 앞서서 실행되고 있다.
  • HttpServletRequest, HttpServletResponse 인터페이스 구현을 SessionRepositoryRequestWrapper, SessionRepositoryResponseWrapper 구현체로 교체한다.
    • SessionRepositoryRequestWrapper에서 getSession()을 오버라이드하고 있다.(session을 가지고 오거나 생성하거나)
  • HttpServletRequest, HttpServletResponse 인터페이스의 Session 처리와 관련한 처리를 오버라이드 한다.
    • Session 관련 생성 및 입출력은 SessionRepository 인터페이스를 통해 처리한다.
    • HttpSession 인터페이스에 대해 Spring Session 구현체 HttpSessionWrapper를 사용하도록 한다.
    • HttpSessionWrapper 구현체는 org.springframework.session.Session 인터페이스를 포함하고 있다.
    • 스토리지 종류에 따라 org.springframework.session.Session 인터페이스 구현체가 달라진다.
profile
꾸준히 나아가자 🐢

0개의 댓글