본문 바로가기
Programming/Study

Spring Security의 인증 처리 흐름

by JKROH 2023. 12. 6.
반응형

 Spring Security를 구현하고 사용하는데, 어떻게 인증이 진행되는지 모르고 코드만 따라치는 건 아무 의미가 없다. 어떻게 로그인이 되는지 정도는 간단하게 알고 가는 것이 기왕 공부하는 의미가 있지 않을까?

 

 일반적인 클라이언트 - 서버 간 소통은 클라이언트가 뭔가 요청을 쏴주면 서버에서 해당 요청을 받고 이에 맞는 적절한 작업을 통해 응답하는 과정이다. 그런데 인증 / 인가가 추가되면 어떨까? 서버는 클라이언트의 모든 요청을 그냥 받고 수행해서 결과물을 반납할까? 그럼 인증 / 인가의 의미가 없지 않을까? 그럼, 나한테 요청을 보낸 사용자를 인증하는 과정은 어디서 일어나야할까? 

 

 해당 과정은 서버가 요청을 받아들이고 일련의 업무를 수행하기 전에 처리되어야 한다. 그러니까 클라이언트 - 서버의 일대일 소통 사이에 뭔가 하나가 요청을 가로채서 이 요청이 적절한지를 미리 검증하고, 적절하다면 해당 사용자의 정보와 요청을 함께 서버에 보내는 것이다. 이러한 과정은 서블릿 필터에서 일어난다. 이러면 또 서블릿은 뭐고 필터는 뭔지에 대해 알아야 하는데... 이 부분은 직접 찾아보시기를 권장한다. 하나 힌트를 주자면, 그냥 빌드 파일 하나 실행시켰는데 도대체 어떻게 내가 지정한 도메인으로 요청이 들어오고, 나는 어떻게 누가 나한테 요청 보냈는지를 알아서 그 사람한테 원하는 자원을 반환하지? 의 이유를 고민하면 서블릿이 무엇인지에 접근할 수 있다. 아무튼, 인증 처리는 이런 서블릿 필터에서 일어난다. 

 

 

서블릿 필터 체인에 끼워넣어진 Spring Security 필터 체인

 

 Spring Security를 적용하면, 서블릿 필터 체인 중간에 인증 처리와 관련한 필터를 끼워넣을 수 있다. 인증 처리가 없을 때는 필터 체인을 따라 죽죽 진행되어 디스패처 서블릿에서 요청이 쏴지던 흐름 중간에 인증 필터를 끼워넣어 잠깐 인증을 처리하는 것이다. 그럼 인증 / 인가를 구현한다는 것은 무엇일까? 이제는 알 수 있다. 우리는 저 중간에 끼워넣어지는 필터를 구현하면 된다.

Spring Security의 인증 처리 흐름

 앞서 본 그림에서 Spring Security 필터 체인의 가장 처음 필터는 UserNamePasswordAuthenticationFilter다. 해당 필터에서 사용자의 로그인 요청을 받아서 본격적인 인증 처리를 시작한다. 순서대로 살펴보자.

  1. 사용자는 로그인 요청을 보낸다.
  2. UserNamePasswordAuthenticationFilter는 해당 요청에 담긴 Username과 Password를 바탕으로 Authentication을 만든다. 이 때 만들어진 Authentication은 아직 인증이 완료된 상태는 아니다.
  3. 만들어진 Authentication을 AuthenticationManager에게 전달한다. 만들어진 Authentication이 적합한지 인증을 요청하는 것이다. AuthenticationManager는 인터페이스다. 이를 구현한 구체 클래스가 ProviderManager다.
  4. AuthenticationManager는 인증 AuthenticationProvider에 Authentication을 넘겨 인증 처리를 맡긴다.
  5. AuthenticationProvider는 UserDetailsService를 통해 UserDetails를 조회한다. UserDetails데이터베이스 등의 저장소에 저장된 사용자의 Username과 사용자의 자격을 증명해 주는 Credential인 Password, 그리고 사용자의 권한 정보를 포함하고 있는 컴포넌트이다.
    1. Credential은 해당 사용자를 증명하기 위한 구체적인 수단을 의미한다. 일반적으로 비밀번호가 사용된다.
  6. 받아온 Authentication의 Username정보를 바탕으로 Credential 저장소에서 Credential을 조회한다.
  7. 조회한 Credential을 기반으로 UserDetails를 생성한다.
    1. 이 때 조회한 Credential에 담긴 비밀번호는 보통 암호화되어있다. 비밀번호를 암호화하지 않고 DB에 저장하지는 않을 것이다.
  8. 생성한 UserDetails를 AuthenticationProvider에 반환한다.
  9. 받아온 UserDetails에 담긴 비밀번호를 PasswordEncoder를 통해 디크립팅 해서 처음 주어진 Authentication에 담긴 비밀번호와 같은지 비교한다. 만일 같다면 인증 처리가 완료된 Authentication을 생성한다.
  10. 인증된 Authentication을 반환한다.
  11. 인증된 Authentication을 반환한다.
  12. 인증된 Authentication을 Security Context에 저장한다. 이후에는 저장된 Authentication을 사용해 Authentication이 포함된 요청이 오면 검증한다.

 생각보다 별 것 없다. 길~게 늘였지만 세 줄 요약을 해보자.

  1. 사용자가 아이디, 비밀번호를 가지고 로그인 요청을 보낸다.
  2. 아이디, 비밀번호를 검증한다.
  3. 검증을 통과하면 다음에도 쓸 수 있게 저장하고, 아니면 거절한다.

 우리가 쉽게 생각할 수 있는 로그인 로직이다. Spring Security를 사용하면, 이렇게 어려움 없이 로그인 로직을 구현할 수 있다.

반응형

댓글