# Spring Security - 주요 아키텍처 이해 [1]

uuuu.jini·2022년 2월 23일
0

Spring Security

목록 보기
4/5
post-thumbnail

🐯 위임 필터 및 필터 빈 초기화 - DelegatingProxyChain, FilterChainProxy

DelegatingFilterProxy

서블릿 필터는 스프링에서 정의된 빈을 주입해서 사용할 수 없다. ( 필터 - 요청을 받아서 자원을 접근하기 전후에 일정한 작업을 처리하는 클래스 이다. ) 서블릿 필터와 스프링 빈은 서로 다른 컨테이너 상에서 동작하므로 주입이 불가한 것이다. 인증/인가와 같은 처리는 스프링 컨테이너에서 생성된 Filter를 통해 처리된다. DelegatingFilterProxy는 실질적인 서블릿 필터로서 특정한 이름을 가진 스프링 빈을 찾아 그 빈에게 요청을 위임한다. springSecuirityFilterChain이름으로 생성된 빈을 ApplicationContext 에서 찾아 요청을 위임하며 실제 보안 처리를 하지 않는다.

서블릿 컨테이너와 스프링 컨테이너 사이의 링크를 제공해주는 서블릿 필터로서 서블릿 필터의 요청을 받아 스프링 컨테이너에 생성된 Filter를 구현한 스프링 빈에 위임한다.

FilterChainProxy

springSecurityFilterChain의 이름으로 생성되는 필터 빈이다. DelegatingFilterProxy로 부터 요청을 위임받고 실제 보안을 처리한다. 스프링 시큐리티 초기화 시 생성되는 필터들을 관리하고 제어한다.(스프링 시큐리티가 기본적으로 생성하는 필터 + 설정 클래스에서 API추가시 생성되는 필터) 사용자의 요청을 필터 순서대로 호출하여 저장한다. 사용자 정의 필터를 생성해서 기존의 필터 전후로 추가가 가능하며(필터의 순서를 잘 정의해야 한다.) 마지막 필터까지 인증 및 인가 예외가 발생하지 않으면 보안을 통과한다.


🐯 필터 초기화와 다중 보안 설정 클래스

WebSecurityCOnfiugerAdapter를 상속받은 설정 클래스가 여러개 일 경우 설정클래스 별로 보안 기능이 각각 작동하며 설정 클래스별로 RequestMatcher와 필터가 생성된다. RequestMatcher와 filter들을 SecurityFilterChain객체에 담겨 있으며 설정 클래스별로 존재하고 여러 설정클래스가 존재할 경우 해당 객체여러개를 FilterChainProxy가 리스트로 가지고 있게 된다. 그래서 , 사용자의 요청이 들어올 경우 FilterChainProxy의 SecurityFilterChains 중 Request에 따라 해당하는 Filters를 선택하여 실행해주게 된다.

스프링 시큐리티가 초기화 될때 순서에 따라 초기화하기 때문에 설정 클래스가 여러개일 경우 @Order(0),(1) 등으로 순서를 지정해주어야 한다. 넓은범위의 요청방식이 순서가 더 낮아야 한다. 좁은 범위의 요청방식이 우선순위가 더높아야만 먼저 체크를 하므로 좁은 범위의 보안 적용이 가능하다.


🐯 Authentication

인증 또는 인증 주체 라고 정의할 수 있으며, 당신이 누구인지 증명하는 것이다.

  • 사용자의 인증 정보를 저장하는 토큰 개념
  • 인증 시 id와 password를 담고 인증 검증을 위해 전달되어 사용된다.
  • 인증 후 최종 인증 결과 ( user 객체, 권한정보 ) 를 담고 SecurityContext 에 저장되어 전역적으로 참조가 가능하다.
  • Authentication authentication = SecurityContexHolder.getContext().getAuthentication() 로 작성하면 Authentication 객체를 얻을 수 있다. --> 전역적으로 인증 결과 참조

Authentication 인터페이스의 구조
1. principal : 사용자 아이디(인증시) 혹은 User 객체(인증 후)를 저장
2. credentials : 사용자 비밀번호
3. authorities : 인증된 사용자의 권한 목록
4. details : 인증 부가 정보
5. Authenticated : 인증 여부 , 인증시 true저장

Authentication 인증 흐름

  • 사용자 로그인 : username + password
  • 위의 내용 전달시 UsernamePasswordAuthenticationFilter 인증 필터가 request정보를 받아서 username password를 추출한 후 Authentication객체를 생성하고 principal속성에 id, credentials 속성에 passowrd를 저장한다. ( 인증 검정 처리에 사용되는 객체 )
  • AuthenticationManager가 인증 객체(Authentication)를 가지고 인증 처리를 한다. (총괄)
  • 인증 실패시 : 예외 발생 & 이후 진행 안됨 , 인증 실패 후속 처리
  • 인증 성공시 : Authentication 객체를 만들고 principal속성에 인증에 성공한 user결과를 저장하고 credentials 에는 password를 담는데 보안상 비워두기도 한다. Authorities에는 권한 목록 등을 담는다. 이게 최종적인 인증결과를 가진 객체이다.
  • 위의 객체를 SecurityContextHolder의 SecurityContext객체안에 인증이 완료된 Authentication객체를 저장하면 전역적으로 사용이 가능해진다.

    Authentication : 인증 정보를 저장하는 토큰 개념, 인증 시/후 에 담는 정보가 다르다.


🐯 인증 저장소

SecurityContext

Authentication 객체가 저장되는 보관소로 필요 시 언제든지 Authentication 객체를 꺼내어 쓸 수 있도록 제공되는 클래스이다. ThreadLocal에 저장되어 아무 곳에서나 참조가 가능하도록 설계되었다. 인증이 완료되면 HttpSession에 저장되어 어플리케이션 전반에 걸쳐 전역적인 참조가 가능하다.

SecurityContext에 Authentication 객체가 저장되고 해당 객체 내에 User객체의 정보가 저장된다. user는 인증 성공시 최종으로 생성된 사용자의 정보이다.

SecurityContextHolder

SecurityContext 객체 저장 방식

  • MODE_THREADLOCAL : 스레드당 SecurityContext 객체를 할당한다.(기본)
  • MODE_INHERITABLETHREADLOCAL : 메인 스레드와 자식 스레드에 관하여 동일한 SecurityContext를 유지한다.
  • MODE_GLOBAL : 응용 프로그램에서 단 하나의 SecurityContext를 저장한다.

SecurityContextHolder.clearContext() : SecurityContext 기존 정보 초기화

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

인증 저장소 흐름

  • 사용자 로그인
  • server가 요청을 받고 하나의 thread를 생성한다.(요청을 받는 스레드로 스레드로컬이라는 전역저장소가 thread마다 할당된다.)
  • 스레드가 인증처리를 하며, 인증 필터가 인증을 한다. ( Authentication객체를 생성 & 로그인 정보를 저장한 후 인증 시도 )
  • 인증 실패시 : .clearContext()를 통해 securityContextHolder안의 securityContext를 null로 초기화
  • 인증 성공시 : SecurityContext객체 안에 최종 인증 성공한 인증 객체를 담는 처리를 한다. (성공 결과등의 정보를 Authentication 객체에 담는다. )
  • 최종적으로 SecurityContext가 httpSession에 저장이 된다.

모드 변경
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);

profile
멋쟁이 토마토

0개의 댓글