SpringBoot 소셜 로그인 구현하기 (with. SpringSecurity 설정 및 FilterChain)

신준호·2023년 10월 28일
0
post-thumbnail

이번 포스팅은 소셜 로그인을 구현하기 전 SpringSercuriy 설정한 과정을 정리할건데 먼저 FilterChian에 대해서 알아보자!!

SecurityConfig

@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();
    }
}

Security Filter Chain

Spring Security 에서 제공하는 인증,인가를 위한 필터들의 모음

가장 핵심이 되는 기능을 제공하며, 거의 대부분의 서비스는 Security Filter Chain에서 실행된다.
기본적으로 제공하는 필터들이 있으며, 사용자는 커스텀 필터 또한 필터 체인으로 포함시켜 사용할 수 있다.

Application Context

Application 초기화 과정에서 사용자가 정의한 Security Filter Chain이 생성된다.

맨 위에 SecurityConfig에서 Security Filter Chain 빈을 생성하는 filterChain 메소드가 전반적인 설정을 하고 매개변수인 HttpSecurity가 설정을 기반으로 Security Filter Chain을 생성한다.

Filter Chain

Http 요청 -> Web Application Server(Servlet Container) -> 필터1 -> 필터2 ..... -> 필터 n -> Servlet -> 컨트롤러

해당 이미지는 초기화 부터 시작해서 사용자의 인증 요청이 어떤 filter을 거쳐 인증/인가가 성공하는지 보여준다.
지금부터, Filter Chain을 구성하는 filter들을 소개해보자!

  • SecurityContextPersistenceFilter : SecurityContextRepository에서 SecurityContext를 가져오거나 생성한다.

  • LogoutFilter: 로그아웃 요청을 처리

  • UsernamePasswordAuthenticationFilter: ID와 Password를 사용하는 실제 Form 기반 유저 인증을 처리한다.

    • Authentication 객체를 만들고 AuthenticationManager에게 인증처리를 맡긴다.
    • AuthenticationManager는 실질적인 인증을 검증 단계를 총괄하는 AuthenticationProvider에게 인증 처리를 위임한다. 그렇게 해서 UserDetailService와 같은 서비스를 사용해서 인증을 검증할 수 있다.
  • ConcurrentSessionFilter: 동시 세션과 관련된 필터(이중 로그인)

  • RememberMeAuthenticationFilter: 세션이 사라지거나 만료 되더라도, 쿠키 또는 DB를 사용하여 저장된 토큰 기반으로 인증을 처리한다.

  • AnonymousAuthenticationFilter: 사용자 정보가 인증되지 않았다면 익명 사용자 토큰을 반환한다.

  • SessionManagementFilter: 로그인 후 Session과 관련된 작업을 처리한다.

  • ExceptionTranslationFilter: 필터 체인 내에서 발생되는 인증, 인가 예외를 처리한다.

  • FilterSecurityInterceptor: 권한 부여와 관련한 결정을 AccessDecisionManager에게 위임해 권한부여 결정 및 접근 제어를 처리한다.

  • HeaderWriterFilter: Request의 HTTP 헤더를 검사해 Header를 추가하거나 빼주는 필터

  • CorsFilter: 허가된 사이트나 클라이언트의 요청인지 검사한다.

  • CsrfFilter: CSRF Tocken을 사용하여 Csrf공격을 막아주는 기능을 제공한다.


다음은 Filter Chain 안에서 설정한 과정을 정리해보자!!

과정

1 .csrf()

CSRF란?

cross site Request forgery로 사이즈간 위조 요청인데, 즉 정상적인 사용자가 의도치 않은 위조요청을 보내는 것을 의미한다.

  • CSRF protection
    • springsecurity에서 default로 설정된다.
    • GET요청을 제외한 POST, PUT, DELETE 요청으로부터 보호한다.
    • html에서 다음과 같은 csrf 토큰이 포함되어야 요처을 받아드려 위조 요청을 방지한다.

  • Rest api에서의 CSRF
    • rest api를 이용한 서버라면 disable()해도 가능하다
    • session 기반 인증과는 다르게 stateless하기 때문에 서버에 인증정보를 보관하지 않는다.
    • client는 권한이 필요한 요청을 하기 위해서는 요청에 필요한 정보를 포함시켜야 한다.
    • 서버에 인증정보를 저장하지 않기 때문에 csrf 코드들을 작성할 필요가 없다.

2 .formLogin()

formLogin이란?

formLogin은 SpringSecurity에서 제공하는 인증방식이다.


1. URL이 인증이 필요한 경우 Server는 Login페이지를 return한다.
2. 사용자가 id와 password를 입력하여 로그인 요청을 하면 Post mapping으로 해당 데이터가 서버에 전송된다.
3. Server는 해당 로그인 정보를 확인한다. 해당 유저 정보가 존재한다면 Session과 Token을 생성하고 저장한다.

  • formLogin을 선언한다.
  • 만약 token방식으로 인증처리를 한다면 disable을 해야한다.

3 .authorizeRequests()

  • 경로에 관한, 인증 설정을 한다는 선언이다.

4 .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()

  • CORS pre-flight 요청에 대한 모든 접근을 허용

5 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)

  • 세션 생성을 "STATLESS"로 설정하여, 서버가 세션을 생성하거나 사용하지 않도록 한다. JWT와 같은 토큰 기반 인증에서 사용한다.

6 .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)

  • 인증 오류가 발생한 경우 "jwtAuthenticationEntryPoint"를 사용하여 예외 처리를 한다.

7 .addFilterBefore(firstFilter, secondFilter.class)

  • 첫 번쨰 인자로 주어진 필터를 두 번쨰 인자로 주어진 필터 전에 SpringSecurity 필터 체인에 추가한다.

8 .build()

  • 지금까지의 설정을 바탕으로 "SecurityFilterChain" 객체를 빌드하여 반환한다.


다음은 SpringSecurity에 JWT 필터 적용한 과정을 정리해보겠다..

profile
개발 공부 일지

0개의 댓글