읽는데 약 2분
spring security 기본 용어
프로젝트의 코드 중 시큐리티에 대한 내용이 잘 이해가 되지 않아 복습하기 위해 작성한 글입니다.
SecurityContextHolder
SecurityContext를 담고 있는 클래스입니다. ThreadLocal 전략을 사용하고 아래와 같은 구조를 띱니다.
위 구조를 아래 사진의 코드를 통해 확인할 수 있습니다.
@EnableWebSecurity
해당 어노테이션을 통해 스프링이 찾을 수 있게 하고 해당 클래스를 global websecurity에 적용할 수 있도록 합니다.
WebSecurityConfigurerAdapter
자신만의 시큐리티 설정을 하고 싶을 때 상속해서 사용하면 됩니다. 상속시 auto-configuration을 사용하지 않게 됩니다. cors, csrf, filter, authenticate, exception handler 등을 설정할 수 있게 됩니다.
AuthenticationManager
어떻게 authenticate를 할지 정의한 인터페이스입니다. 반환된 authentication 객체는 AuthenticationManager를 호출한 컨트롤러에 의해 SecurityContextHolder 안에 저장됩니다.
UsernamePasswordAuthenticationToken
UsernamePasswordAuthenticationToken은 AbstractAuthenticationToken을 상속받고 AbstractAuthenticationToken은 Authentication을 구현한 추상 클래스입니다.
UsernamePasswordAuthenticationToken을 이용해서 AuthenticationManager은 인증을 진행하고 인증된 객체를 SecurityContextHolder에 담게 됩니다. 이 토큰을 생성하는 부분은 코드에서 두 군데가 있습니다. 첫번째는 login API를 호출하는 부분입니다.
이는 Token의 두가지 생성자 중 첫 번째 생성자를 호출하게 됩니다. setAuthenticated(false);
가 호출됨을 알 수 있습니다. 즉 인증되지 않은 토큰을 생성한 부분입니다.
두번째는 커스텀 필터를 구현한 부분입니다. 요청 헤더에 JWT 필드가 존재한다면 사용자의 정보를 파싱해서 토큰을 생성한 후 SecurityContextHolder에 UsernameAuthenticationToken을 담는 것을 확인할 수 있습니다.
이때 호출되는 생성자를 확인해보면 setAuthenticated(true)
가 포함됨을 알 수 있습니다.
그리고 시큐리티 설정 클래스에 loginForm() 설정을 하게 되면 UsernamepasswordAuthenticationFilter가 활성화 되지만 하지 않는다면 활성화 되지 않는 것을 확인할 수 있습니다.
[fomrLogin() 없을 때]
[fomrLogin() 있을 때]
프로젝트에서는 jwt인증방식을 사용하므로 UsernamePasswordAuthenticationFilter를 대체할 custom Filter을 사용하게 됩니다. 해당 필터가 작동되는 순서를 정하기 위해 addFilterBefore()
을 사용하게 됩니다.
UserDetailsService
AuthenticationManager의 구현체인 ProviderManager은 인증에 대한 구현을 AuthenticationProvider에게 위임합니다. AuthenticationProvider은 사용자 이름을 기반으로 사용자 세부 정보를 검색하기 위해 UserDetailsService를 사용합니다. 이는 interface로 데이터베이스에서 사용자 정보를 얻기 위해 loadUserByUsername 메서드를 구현해야합니다. UserDetails를 리턴하며 아래 사진은 DaoAuthenticationProvider
가 UserDetailsService를 사용하는 코드입니다.
authenticationManagerBean
AuthenticationManager을 외부에서 사용하기 위해 authenticateManagerBean을 사용했습니다. 시큐리티에 아래와 같은 설정을 추가함으로써 Controller에서 AuthenticationManager을 주입하여 사용할 수 있게 됩니다.
authenticationManagerBuilder
애플리케이션에 적합한 UserDetails를 구현한 클래스를 얻기 위해 UserDetailsService를 customize를 했다면 AuthenticationProvider에게 알려주어야합니다. 이는 아래 메서드를 override함으로써 가능합니다.
exceptionHandling.authenticationEntryPoint
ExceptionTranslationFilter은 2가지 종류의 예외에 대해서 처리합니다. 인증예외처리와 인가예외처리가 있는데 이 중 authenticationEntryPoint는 인증예외처리를 담당합니다.