Red Glitter Pointer

 

 

 

스프링 시큐리티를 사용하면
인증 / 인가를 편리하게 구현할 수 있다.

 

 

 

스프링 시큐리티란?

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

 

 

 

보안 언어 정리

이름 설명
인증(Authentication) 접근하려는 유저가 누구인지 확인하는 절차
ex) 회원가입하고 로그인
인가(Authorization) '권한 부여'나 '허가'와 같은 의미로 사용된다. 인증된 사용자에 대해 권한을 확인하고 허락하는 것
접근 주체(Principal) 보호된 대상에 접근하는 유저
비밀번호(Credential) 대상에 접근하는 유저의 비밀번호
권한(Role) 인증된 주체가 어플리케이션의 동작을 수행할 수 있도록 허락되었는지를 결정할 때 사용

 

✔️ 사용자가 게시글을 작성하기 위해 로그인을 했다 ? 👉 인증

✔️ 다른 사람이 작성한 게시글의 수정하기 버튼을 눌렀지만 수정할 수 없었다 👉 인가

 

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

 

 

 

 

Credential 기반의 인증 방식

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

 

 

 

 

 

서블릿 필터

 

스프링 시큐리티는 필터(Filter) 기반으로 동작하기 때문에 스프링 MVC와 분리되어 관리 및 동작한다.

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

 

 

 

📌 FilterChainProxy

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

 

🤔 DelegatingFilterProxy 에서 바로 SecurityFilterChain 을 실행시킬 수 있지만 중간에 FilterChainProxy 를 둔 이유 ?

서블릿을 지원하는 시작점 역할을 하기 위함! 이를 통해 서블릿에서 문제가 발생할 경우, FilterChainProxy의 문제라는 것을 알 수 있다. 또한 FilterChainProxy에서 어떤 체인에게 작업을 위임할지도 결정할 수 있다.

 

 

 

📌 SecurityFilterChain

인증을 처리하는 여러 개의 시큐리티 필터를 담는 필터 체인이다.

여러 개의 SecurityFilterChain을 구성하여 매칭되는 URL에 따라 다른 SecurityFilterChain이 사용되도록 할 수 있다.

 

 

 

📌 SecurityFilters

요청을 스프링 시큐리티 매커니즘에 따라 처리하는 필터!

SecurityFilters에는 순서가 존재한다.

 

 

 

 

 

 

아키텍처

Username과 Password 방식의 아키텍처는 아래와 같다.

스프링 시큐리티는 기본적으로 세션-쿠키 방식으로 인증한다.

 

 

  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 와 응답을 내려줌

 

 

📌 AuthenticationFilter

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

 

 

📌 UsernamePasswordAuthenticationToken

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

 

 

📌 AuthenticationManager

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

 

 

📌 ProviderManager

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

 

 

📌 AuthenticationProvider

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

 

 

📌 UserDetailsService

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

 

 

📌 UserDetails

  • 사용자의 정보를 담는 인터페이스
메소드 설명
getAuthorities() 계정의 권한 목록을 리턴
getPassword() 계정의 비밀번호 리턴
getUsername() 계정의 고유한 값 리턴
isAccountNonExpired() 계정의 만료 여부 리턴
isAccountNonLocked() 계정의 잠김 여부 리턴
isCredentialsNonExpired() 비밀번호 만료 여부 리턴
isEnabled() 계정의 활성화 여부 리턴

 

 

📌 SecurityContextHolder

 

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

 

 

📌 SecurityContext

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

 

 

📌 Authentication

  • 현재 접근하는 주체의 정보와 권한을 담는 인터페이스
  • AuthenticationManager.authenticate(Authentication)에 의해 인증된 principal 혹은 token
 이름 설명
principal 사용자 정보
authorities 사용자에게 부여된 권한
ex) ROLE_ADMIN
credentials 자격 증명

 

 

 

 

 

 

+ Recent posts

loading