[이론편] 스프링 시큐리티란 ?

mallin·2022년 1월 24일
7

스프링 시큐리티

목록 보기
1/2
post-thumbnail

스프링에서 제공하는 공식 문서 ➡️ https://spring.io/projects/spring-security

스프링 시큐리티란 ?

스프링 기반의 애플리케이션의 보안(인증과 권한, 인가 등)을 담당하는 스프링 하위 프레임워크

한줄 설명에서 인증, 인가 라는 말이 나오는데 이거 두개가 동일한게 아닌가 ? 라는 생각이 들 수 있다. 사실 나도 그랬다
https://media.giphy.com/media/3o7buirYcmV5nSwIRW/giphy.gif

그렇기 때문에 스프링 시큐리티에 대해 본격적인 정리를 들어가기 전에 먼저 보안 관련 단어들을 정리하고 들어가자

🔐 보안 언어 정리

이름설명
인증 (Authenticate)접근하려는 유저가 누구인지 확인하는 절차
EX) 회원가입하고 로그인
인가 (Authorization)인증된 사용자에 대해서 권한을 확인하고 허락하는 것
접근 주체 (Principal)보호된 대상에 접근하는 유저
비밀번호 (Credential)대상에 접근하는 유저의 비밀번호

인증과 인가에 대해서 예시를 들어보자면

한 사용자가 velog 에 글을 작성하기 위해서 로그인을 했다 ➡️ 인증
로그인 한 사용자가 신나게 글을 썼다. 그리고 다른 사람 글을 수정하기 위해서 권한을 확인해봤지만 수정할 수 없었다 ➡️ 인가

그니깐 간단하게 생각해서 사이트에 대해서 유효한 사용자인지 확인하는 것이 인증 이고, 인증된 사용자가 사용할 수 있는 기능인지 확인하는게 인가 라고 생각하면 된다 그렇기 때문에 인증이 먼저 이루어 지고 인가가 이뤄져야 한다.

Spring Security 에서는 이러한 인증, 인가를 위해 Principal 을 아이디로 Credential 을 비밀번호로 사용하는 Credential 기반의 인증 방식을 사용한다.


서블릿 필터

https://blog.kakaocdn.net/dn/ck7IkP/btqRqcv8uUf/fIwnelVOa3m7dHRDcmABVk/img.png
출처 : https://limdevbasic.tistory.com/19

스프링 시큐리티는 서블릿의 필터를 기반으로 동작한다.

사용자의 요청이 서블릿에 전달되기 전, 스프링 시큐리티는 필터의 생명주기를 이용해서 인증과 권한 작업을 수행 하지만, 서블릿 컨테이너는 스프링 컨테이너에 등록된 빈을 인식할 수 없다.

그렇기 때문에 스프링 시큐리티에서는 DelegatingFilterProxy 라는 서블릿 필터의 구현체를 제공한다. DelegatingFilterProxy 는 서블릿 매커니즘으로 서블릿의 필터로 등록될 수 있으며, 스프링에 등록된 빈을 가져와서 의존성을 주입할 수도 있다. 결론적으로 서블릿 컨테이너의 생명주기와 스프링의 ApplicationContext 사이를 연결하는 다리 역할을 하게된다.

FilterChainProxy

DelegatingFilterProxy 를 통해 받은 요청과 응답을 스프링 시큐리티 필터체인에 전달하고 작업을 위임하는 역할을 한다.

🤔 DelegatingFilterProxy 에서 바로 SecurityFilterChain 을 실행시킬 수 있지만 중간에 FilterChainProxy 를 둔 이유 ?
➡️ 서블릿을 지원하는 시작점 역할을 하기 위함이다. 이를 통해 서블릿에서 문제가 발생하는 경우 FilterChainProxy 의 문제라는 걸 알 수 있다.
또한, FilterChainProxy 에서 어떤 체인에게 작업을 위임할지도 결정할 수 있음

SecurityFilterChain

인증을 처리하는 여러 개의 시큐리티 필터를 담는 필터 체인
여러 개의 SecurityFilterChain 을 구성하여 매칭되는 URL 에 따라 다른 SecurityFilterChain 이 사용되도록 할 수 있다

SecurityFilters

요청을 스프링 시큐리티 매커니즘에 따라 처리하는 필터
SecurityFilters 에는 순서가 존재함


아키텍처

Username and Password 방식의 아키텍처는 다음과 같다.
spring security 는 기본적으로 세션-쿠키 방식으로 인증한다
https://blog.kakaocdn.net/dn/Svk8p/btqEIKlEbTZ/vXKzokudAYZT9kRGXNHJe1/img.png

  1. 유저가 로그인 요청 (Http Request)
  2. AuthenticationFilter 에서 UsernamePasswordAuthentication Token 을 생성하여 AuthenticationManager 에 전달
  3. AuthenticationManager 은 등록된 AuthenticationProvider 들을 조회하여 인증 요구
  4. AuthenticationProvider 은 UserDetailService 를 통해 입력받은 아이디에 대한 사용자 정보를 User(DB) 에서 조회
  5. User 에 로그인 요청한 정보가 있는 경우 UserDetails 로 꺼내서 유저 session 생성
  6. 인증이 성공된 UsernameAuthenticationToken 을 생성하여 AuthenticationManager 로 반환
  7. AuthenticationManager 은 UsernameAuthenticationToken 을 AuthenticationFilter 로 전달
  8. AuthenticationFilter 은 전달받은 UsernameAuthentication 을 LoginSuccessHandler 로 전송하고, spring security 인메모리 세션저장소인 SecurityContextHolder 에 저장
  9. 유저에게 session ID 와 응답을 내려줌

1. AuthenticationFilter

  • Spring Security 는 연결된 필터를 가지고 있음
  • 모든 Request 는 인증과 인가를 위해서 이 필터를 통과
  • SecurityContext 에 사용자의 세션 ID 가 있는지 확인 하고 세션 ID 가 없는 경우 다음 로직 수행
  • 인증 성공하는 경우 인증된 Authentication 객체를 SecurityContext 에 저장 후 AuthenticationSuccessHandler 실행
  • 인증 실패하는 경우 AuthenticationFailureHandler 실행

2. UsernamePasswordAuthenticationToken

  • Authentication을 구현한 AbstractAuthenticationToken의 하위 클래스
  • principal ➡️ username / credentials ➡️ password
  • UsernamePasswordAuthenticationToken(Object principal, Object credentials) : 인증 전의 객체를 생성
  • UsernamePasswordAuthenticationToken(Object principal, Object credentials,Collection<? extends GrantedAuthority> authorities) : 인증 완료된 객체를 생성

3. AuthenticationManager

  • Authentication 을 만들고 인증을 처리하는 interface
  • 로그인시 인자로 받은 Authentication 을 Provider 를 통해 유효한지 처리하여 Authentication 객체를 리턴한다.

ProviderManager

  • AuthenticationManager 의 구현체
  • 사용자 요청을 인증에 필요한 AuthenticationProvider 를 살펴보고 전달된 인증 객체를 기반으로 사용자 인증 시도

4. AuthenticationProvider

  • 실제 인증을 담당하는 인터페이스
  • 인증 전 Authentication 객체를 받아서 DB 에 있는 사용자 정보를 비교하고 인증된 객체를 반환

5. UserDetailsService

  • DB 에서 유저 정보를 가져오는 역할
  • loadUserByUsername() 메소드를 통해서 DB 에서 유저 정보를 가져온다.
  • 커스텀하게 사용하고 싶다면 해당 interface 를 implements 받아서 loadUserByUsername() 메소드를 구현하면 됨

6. UserDetails

  • 사용자의 정보를 담는 인터페이스

기본 오버라이드 메소드 ⬇️

메소드설명
getAuthorities()계정의 권한 목록을 리턴
getPassword()계정의 비밀번호 리턴
getUsername()계정의 고유한 값 리턴
isAccountNonExpired()계정의 만료 여부 리턴
isAccountNonLocked()계정의 잠김 여부 리턴
isCredentialsNonExpired()비밀번호 만료 여부 리턴
isEnabled()계정의 활성화 여부 리턴

7. SecurityContextHolder

SecurityContextHolder

  • SecurityContext 를 현재 스레드와 연결 시켜주는 역할
  • 스프링 시큐리티는 같은 스레드 의 어플리케이션 내 어디서든 SecurityContextHolder 의 인증 정보를 확인 가능하도록 구현되어 있는데 이 개념을 ThreadLocal 이라고 함.

SecurityContext

  • Authentication 의 정보를 가지고 있는 interface
  • SecurityContextHolder.getContext() 를 통해 얻을 수 있음

Authentication

  • 현재 접근하는 주체의 정보와 권한을 담는 인터페이스
  • AuthenticationManager.authenticate(Authentication) 에 의해 인증된 principal 혹은 token

이름설명
Principal사용자 정보
authorities사용자에게 부여된 권한
EX) ROLE_ADMIN
credentials자격 증명

🙇🏻‍♀️ 레퍼런스

2개의 댓글

comment-user-thumbnail
2022년 5월 27일

감사합니다 정말 잘 봤습니다 OTL,

답글 달기
comment-user-thumbnail
2023년 2월 18일

정말 잘봤어요 덕분에 답답한 것 풀고 갑니다

답글 달기