본문 바로가기
Backend/Spring

Spring Security

by DooDuZ 2024. 6. 13.

인증(Athentication)

인증이란 사용자가 누구인지 확인하는 단계를 의미한다. 로그인을 예로 들면, 아이디와 패스워드를 통해 인증에 성공하는 경우 사용자 정보, 권한 등이 포함된 토큰이 발급된다. 일반적으로 JWT(Json Web Token) 형식을 사용한다.

인가(Authorization)

인가란 인증을 통해 검증된 사용자가 애플리케이션 내부의 리소스에 접근할 때 접근 주체(principal)가 해당 리소스에 접근할 권리가 있는지 확인하는 과정을 말한다. 일반적으로 사용자가 인증 단계에서 발급받은 토큰은 인가 내용을 포함하고 있으며, 사용자가 리소스에 접근하면서 토큰을 함께 전달하면 애플리케이션 서버는 토큰을 통해 권한 유무 등을 확인해 인가를 수행한다.

Spring Security

스프링 시큐리티는 애플리케이션의 인증과 인가를 손쉽게 구현할 수 있게 해주는 라이브러리다. 다양한 인증 및 인가 방식과 보안 기능을 제공하여 애플리케이션의 보안을 관리할 수 있도록 한다.

동작 구조

스프링 시큐리티는 서블릿 필터(Servlet Filter)를 기반으로 동작한다. 클라이언트의 요청은 Dispatcher Servlet에 도달하기 전에 Spring의 필터 체인(Filter Chain)을 거치게 되는데, 여기서 DelegatingFilterProxy내부에 있는 FilterChainProxy를 통해 보안 필터들을 거치게 된다. FilterChainProxy는 스프링 부트에 의해 자동 생성 되며, DelegatingFilterProxy는 이를 Application Context로부터 주입받아 사용하게 된다.

 

 

인증 과정

 

클라이언트로부터 요청을 받으면 서블릿 필터에서 SecurityFilterChain으로 작업이 위임된다. UsernamePasswordAuthenticationFilter(AuthenticationFilter)에서 인증을 처리한다. 만약 인증이 실패하는 경우, 해당 필터는 로그인 폼을 내보내게 된다.

 

  1. UsernamePasswordAuthenticationFilter는 username과 password를 추출하여 토큰을 생성한다.
  2. AuthenticationManager에게 토큰을 전달한다. 일반적으로 사용되는 구현체는 ProviderManagaer이며, ProviderManager는 Authentication Provider에게 토큰을 전달한다.
  3. Authentication ProviderUserDetailsService에 다시 토큰을 전달한다. 변경 없이 security의 기본 설정들을 사용하는 경우에도 개발자는 UserDetailsService UserDetails 인터페이스의 구현 클래스를 작성해야 한다.
  4. password인코딩에는 BCryptPasswordEncoder가 주로 사용된다. UserDetailsService는 전달받은 정보를 통해 DB에서 일치하는 사용자를 찾고 UserDetails 객체를 생성하여 Authentication Providers로 전달한다. 여기서 인증을 진행한다.
  5. 인증이 완료되면 권한을 담은 토큰이 ProviderManager로 전달되고, 이는 다시 AuthenticationFilter로 전달된다. 
  6. 검증된 토큰은 SecurityContextHolder에 있는 SecurityContext에 저장된다.

 

 

이때 별도로 토큰 사용을 위한 구현을 하지 않으면 Spring Security를 통한 로그인은 session 기반 인증이 된다. 클라이언트는 쿠키를 통해 session id를 받고 사용하게 되는데, 이는 서버가 사용자의 상태를 유지해야 하고 서버 메모리를 사용하게 되므로 근래에는 선호되지 않는 것 같다. 하여 조만간 JWT 관련 포스팅을 올릴 예정이다.