초기화 과정부터 한번 살펴보자
SpringSecurity가 초기화 되면서 사용자가 설정한 Api 구성대로 HttpSecurity클래스가 필터들을 생성한다. 이후에 생성된 필터들은 WebSecurity 클래스로 전달하게 된다 그리고 다시 FilterChainProxy에게 빈객체를 생성자로 생성하여 WebSecurity에서 전달받은 Filter들을 FilterChainProxy 에게 전달한다 그러면 FilterChainProxy 는 사용자가 설정한 2개의 설정 클래스들을 가지게 된다.
DelegatingFilterProxy 이클래스는 servlet필터 인데 이클래스도 초기화 될때 이미 FilterChainProxy 빈으로 생성된다
DelegatingFilterProxy 는 springSecurityFilterChain(특정한이름?) 이라는 이름을 찾는데 그 빈이FilterChainProxy다
DelegatingFilterProxy 는 사용자가 요청을 했을때 요청을 받아서 요청을 처리 하지 않고 특정한 이름을 가진 빈에게 요청을 위임하게 되는데, 즉 springSecurityFilterChain이름을 가진 빈이 FilterChainProxy이기때문에 SpringSecurity는 내부적으로 요청을FilterChainProxy전달해준다.
여기까지가 SpringSecurity초기화 과정이다. 요약을 하자면 !
사용자가 두개의 설정클래스를 만들었다면 초기화 될때 필더들이 생성되어 WebSecurity에게 전달 되고 WebSecurity는 FilterChainProxy빈 객체를생성해서 WebSecurity으로 전달받은 Filter들을 FilterChainProxy에게 전달하게 된다 FilterChainProxy는 각각의 필터 목록을 가지게 되고 DelegatingFilterProxy가 springSecurityFilterChain(특정한이름)이름을 가진 빈을 찾게되고 그빈이 FilterChainProxy이므로SpringSecurity는 요청을 FilterChainProxy에게 위임하게 된다.
먼저 인증을 시도하는 경우를 보자
사용자가 인증을 시도하게 되면 delegatingFilterProxy가 요청을 받게 되고 FilterChainProxy에게 요청을 위임하게 된다.
FilterchainProxy는 초기화 되면서 전달받은 필터 목록들을 가지고 있는데 사용자에게 받은 요청을 처리 할 수 있게 각각의 필터들을 호출하여 요청을 위임하게 된다. 필터들은 chain으로 연결되어서 자기 역활이 끝나면 그다음 필터로 이동하게 된다.
SecurityContextPersistenceFilter
- HttpSessionSecurityContextRepository 를 가지고 있는데 이클래스가 SecurityContext객체를 생성하고 session에 저장한다
- session에 저장된 SecurityContext를 다시 조회하고 참조하는 역할을 한다
- 사용자가 이전에 SecurityContext객체가 생성되어서 Session에 저장된 이력이 있는지 체크를 하게된다 현재 사용자는 처음으로 인증을 시도 하기 때문에 Session에 SecurityContext가 생성된적이 없기 때문에 CreateSecurity 에서 새로운 SecurityContext를 생성하해서 SecurityContextHolder안에 저장하게된다.
UsernamePasswordAuthenticationFilter
- 이필터가 실질적으로 폼인증을 처리 하는 인증필터이다.
- Authenticaiton(인증객체)를 만들어서 아이디와 패스워드를 담아서 AuthenticationManager에게 전달한다
- AuthenticationManager 인증을 AuthenticationProvider에게 위임하고 AuthenticationProvider에서 검증단계를 총괄한다
- AuthenticationProvider는 UserDetailsService를 참조해서 사용자의 아이디와 패스워드를 검증하게 된다
- 인증에 성공하게 되면 새로운 Authentication을 생성해서 인증결과를 담고 이후에 SecurityContext에 저장한다
- SecurityContext는 SecurityContextPersistenceFilter 여기서 생성되었던 Authentication(인증객체)꺼내오고 참조 해서 비교후에 일치하면 Authentication(인증객체)를 SecurityContext에 저장하게된다.
SessionManagementFilter
- SessionManagementFilter들이 가지고 있는 3가지의 처리과정이 있는데 이 과정이 인증을 시도하는 시점에 동시에 처리를 하게된다 인증에 성공하게 되면 ConcurrentSession(동시세션)을 체크 하게 되는데 지금 인증을 시도하는 사용자가 이전에 동일한 계정으로 로그인을 한적이 있는지 체크하게된다.
- 개발자가 최대 허용한 Session 개숫를 1개로 했다면 SessionAuthenticationException이 호출되어 사용자가 인증 시도를 차단해버린다.
- 사용자가 인증에 성공한 시점에는 새로운 쿠키가 발급된다 인증을 시도하기전에 있던 쿠키는 소멸되고 다시 세션이 생성되고 새로운 쿠키가 발급되도록 SessionFixation이 호출되고 RegisterSessionInfo를 호출하여 사용자의 세션정보가 저장되어진다.
- 인증을 성공한 이후에는 Handler 후속작업을 처리 하는데 이동하려는 페이지로 접근 하기전에 클라이언트에게 SecurityContext객체를 session에 저장한다
자원에 접근하는 경우를 살펴보자
- 사용자가 인증에 성공한 이후에 자원에 접근하려고 시도하면 delegatingFilterProxy 가 요청을 받고 동일하게 그요청을 FilterChainProxy에게 위임하게 된다.이후에 FilterChainProxy가 가지고 있는 각각의 필터들을 호출하여 요청을 위임하고 역할이 끝나면 다른 필터로 전달하게 된다.
SecurityContextPersistenceFilter
- loadContext메소드가 사용자 Session에 SecurityContext를 저장한적이 있는지 없는지 확인을 한다
- 인증을 성공한 당시 SecurityContext에있는 Authentication(인증객체)를 Session에 저장한 이력이 남아 있다면 SecurityContext를 가져와서 SecurityContextHolder에 저장한다.이렇게 되면 새로운 SecurityContext를 생성하지 않아도 인증에 성공하게 된다.
ConcurrentSessionFilter
- 이필터도 동시적인?세션에 관련된 처리를 하는 필터인데 현재 사용자는 하나다 그렇기 때문에 다음필터로 이동하게 된다.
- 이필터는 최소한 동일한 계정으로 두명 이상이 접속을 시도하는 경우에 이필터가 호출된다.
- 매요청 마다 현재 사용자가 session이 만료되었는지 확인한다 첫번째 사용자의 세션을 만약에 만료 했다면 사용자의 아이디가 로그아웃 되고 응답을 하게된다.
RememberMeAuthenticationFilter
- 현재 사용자가 세션이 만료되거나 무효화 되면 Session안에 SecurityContext안에 있는 Authentication 인증객체가 널이고, 현재 사용자가 요청하는 requestHader에 remember-meCookie 값을 저장한 상태로 서버에 접속을 시도 했다면 사용자 대신에 인증을 시도하게 된다. 만약 인증을 받은 사용자가 접속 했을경우에는 호출되지 않는다 그리고 현재 사용자는 RememberMe기능을 활성화 하지 않고 인증을 시도 했기 때문에 호출하지 않고 그 다음 필터로 이동한다
AnonymousAuthenticationFilter
- 익명 사용자가 인증 시도도 하지 않고 권한도 없이 서버 자원에 접근을 시도하는 경우에 AnonymousAuthenticationFilter가 호출된다.
- 지금은 인증된 사용자이기 때문에 호출되지 않는다 만약 사용자가 익명 사용자라고 한다면 AnonymousAuthenticationToken을 만들어서 SecurityContext에 저장한다 이후에 현재 사용자가 익명사용자인지 인증된 사용자인지 판단하게 된다.
SessionManagementFilter
- 요청을 처리하는데 이필터는 조건이 현재 Session에 SecurityContext가 없는경우이다, 그리고 Session이 만료되거나 무효화 되는경우 이필터가 3가지 과정을 거치게 된다. 현재 사용자가 동일한 계정으로 접근을하는지 아니면 우회 해서 접근을 하는지 체크하게된다.
- 지금은 이조건에 부합되지 않기 때문에 호출되지 않는다
ExceptionTranslationFilter , FilterSecurityInterceptor
- 실적으로 인증이후 사용자가 자원에 접근할때 가장 중요한 역할을 하는 필터들이다.
- ExceptionTranslationFilter 는 인증이나 인가예외가 발생하면 처리하는 필터이다. 이필터는 Try , Cathch 로 묶은 다음에 그다음 필터로 바로 이동해 버린다. ExceptionTranslationFilter 이필터는 인증을 처리 하지않고 예외만 처리하는 필터다
- FilterSecurityInterceptor에서 생기는 모든예외는 ExceptionTranslationFilter에서 하게된다.
- 그리고 두가지 체크를 하는데 현재 접속한 사용자가 SecurityContext안에 Authentication이 존재하는지 확인하는데
- SecurityContext안에 Authentication이 존재하지 않는다면 그즉시 인증예외를 발생시킨다. 인증객체가 없으면 인가처리를 할수가 없다
- 인가처리는 사용자의 정보를 참조해서 사용자가 가진 권한을 봐야 하기 때문에 Authentication이 존재하지 않으면 AuthenticationException(인증예외) 를 발생시킨다. 만약 사용자가 인증객체를 가지고 있다면 AccessDecisionManager에서 인가처리를 하게 된다. 실질적으로는 AccessDecisionManager는 인터페이스 이기 때문에 AccessDecisionVoter를 호출하여 최종적으로 승인 / 거부 를 결정하여 인가처리를 하게 된다. 만약에 사용자가 권한이 없다면 AccessDeniedException(인가예외)를 발생시킨다.
SpringSecurity 각 필터와 아키텍쳐를 공부하면서 느낀점은 일단 너무 많타.. 이 많은 필터와 아키텍쳐들을 어떻게 다 이해하고 써야할지.. 막막하다.... 프로젝트 하면서도 SpringSecurity를 사용했지만 이렇게 까지 공부하면서 구현하지 않았다. 지금 이렇게 하는 이유는 보안이 먼저 보장되어야 사용하는 사람도 마음편하게 사용할수 있지 않을까 라는 생각부터 시작된거 같다 !! 그래서 Security를 적용해서 프로젝트를 진행해보려 한다 혼자서!! 될까?.. ㅋㅋㅋㅋㅋㅋ 될까?...... ㅋㅋㅋㅋㅋㅋ 도전이다!
'SpringSecurity' 카테고리의 다른 글
SpringSecurity(사용자 DB등록 및 PasswrodEncoder) (0) | 2020.11.15 |
---|---|
SpringSecurity 프로젝트 구성 (0) | 2020.11.13 |
SpringSecuirty(AccessDecisionManager,AccessDecisionVoter) (0) | 2020.11.11 |
SpringSecurity(Authorization,FilterSecurityInterceptor) (0) | 2020.11.10 |
SpringSecurity(AuthenticationProvider) (0) | 2020.11.09 |