이번 포스팅은 소셜 로그인을 구현하기 전 SpringSercuriy 설정한 과정을 정리할건데 먼저 FilterChian에 대해서 알아보자!!
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtTokenProvider jwtTokenProvider;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final JwtExceptionFilter jwtExceptionFilter;
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter(jwtTokenProvider);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin().disable()
.authorizeRequests()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers(
"/api/members/kakao/**",
"/api/members/naver/**",
"/api/members/reissue").permitAll()
.antMatchers(HttpMethod.GET, "/api/routine/**").permitAll()
.antMatchers(
"/swagger-ui/**",
"/v3/api-docs/**",
"/swagger-ui.html").permitAll()
.antMatchers("/profile/**", "/routine/**").permitAll()
.anyRequest().authenticated()
.and()
.cors()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint);
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore(jwtExceptionFilter, jwtAuthenticationFilter().getClass());
return http.build();
}
}
Spring Security 에서 제공하는 인증,인가를 위한 필터들의 모음
가장 핵심이 되는 기능을 제공하며, 거의 대부분의 서비스는 Security Filter Chain에서 실행된다.
기본적으로 제공하는 필터들이 있으며, 사용자는 커스텀 필터 또한 필터 체인으로 포함시켜 사용할 수 있다.
Application 초기화 과정에서 사용자가 정의한 Security Filter Chain이 생성된다.
맨 위에 SecurityConfig에서 Security Filter Chain 빈을 생성하는 filterChain 메소드가 전반적인 설정을 하고 매개변수인 HttpSecurity가 설정을 기반으로 Security Filter Chain을 생성한다.
Http 요청 -> Web Application Server(Servlet Container) -> 필터1 -> 필터2 ..... -> 필터 n -> Servlet -> 컨트롤러
해당 이미지는 초기화 부터 시작해서 사용자의 인증 요청이 어떤 filter을 거쳐 인증/인가가 성공하는지 보여준다.
지금부터, Filter Chain을 구성하는 filter들을 소개해보자!
SecurityContextPersistenceFilter : SecurityContextRepository에서 SecurityContext를 가져오거나 생성한다.
LogoutFilter: 로그아웃 요청을 처리
UsernamePasswordAuthenticationFilter: ID와 Password를 사용하는 실제 Form 기반 유저 인증을 처리한다.
ConcurrentSessionFilter: 동시 세션과 관련된 필터(이중 로그인)
RememberMeAuthenticationFilter: 세션이 사라지거나 만료 되더라도, 쿠키 또는 DB를 사용하여 저장된 토큰 기반으로 인증을 처리한다.
AnonymousAuthenticationFilter: 사용자 정보가 인증되지 않았다면 익명 사용자 토큰을 반환한다.
SessionManagementFilter: 로그인 후 Session과 관련된 작업을 처리한다.
ExceptionTranslationFilter: 필터 체인 내에서 발생되는 인증, 인가 예외를 처리한다.
FilterSecurityInterceptor: 권한 부여와 관련한 결정을 AccessDecisionManager에게 위임해 권한부여 결정 및 접근 제어를 처리한다.
HeaderWriterFilter: Request의 HTTP 헤더를 검사해 Header를 추가하거나 빼주는 필터
CorsFilter: 허가된 사이트나 클라이언트의 요청인지 검사한다.
CsrfFilter: CSRF Tocken을 사용하여 Csrf공격을 막아주는 기능을 제공한다.
CSRF란?
cross site Request forgery로 사이즈간 위조 요청인데, 즉 정상적인 사용자가 의도치 않은 위조요청을 보내는 것을 의미한다.
formLogin이란?
formLogin은 SpringSecurity에서 제공하는 인증방식이다.
1. URL이 인증이 필요한 경우 Server는 Login페이지를 return한다.
2. 사용자가 id와 password를 입력하여 로그인 요청을 하면 Post mapping으로 해당 데이터가 서버에 전송된다.
3. Server는 해당 로그인 정보를 확인한다. 해당 유저 정보가 존재한다면 Session과 Token을 생성하고 저장한다.
다음은 SpringSecurity에 JWT 필터 적용한 과정을 정리해보겠다..