Spring Security 동작과정

    용어정리

    Authentication: 인증

    주체(Principal)의 Identity를 증명하는 과정

    자신을 인증해달라고 Credential을 제시함

    주체가 유저일 경우 크레덴셜은 대개 비밀번호임

     

    Authorization: 권한 부여

    인증을 마친 유저에게 권한(Authority)을 부여해 애플리케이션의 특정 리소스에 접근할 수 있도록 허가 하는 과정

    Authorization은 반드시 Authentication 이후에 수행되어야 함

    Authority는 롤 형태로 부여하는 것이 일반적임

     

    Access Control: 접근 제어

    애플리케이션의 리소스에 접근하는 행위를 제어함

    어떤 유저가 어떤 리소스에 접근하도록 허락할지 결정

     


     

    전체 흐름

    Spring Security, 제대로 이해하기 - FilterChain (kyeongsun.com)

     


    초기 설정

     

    Spring Security에서는 인증과 인가에 대한 처리를 여러 개의 필터를 연쇄적으로 실행해서 수행함

    설정에 따라서 필요한 필터가 달라짐

     

    그 설정을 WebSecurityConfingureAdapter를 구현한 설정 파일(SecurityConfig.java)의 내용을 기반으로 해당되는 필터를 생성함. 실제 필터를 생성하는 클래스는 HttpSecurity class임

    package com.betweenourclothes.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.config.http.SessionCreationPolicy;
    import org.springframework.security.crypto.factory.PasswordEncoderFactories;
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    @Configuration
    @EnableWebSecurity //기본적인 Web 보안 활성화
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception{
            http
                    .formLogin().disable() // 기본 제공 form 비활성화
                    .httpBasic().disable() // 기본 alert창 비활성화
                    .csrf().disable() // api 서버 개발 --> 비활성화
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // jwt 사용
                    .and()
                    .authorizeRequests() // HttpServletRequest를 사용하는 요청들에 대한 접근제한 설정
                    .antMatchers("/api/v1/auth/sign-up",
                                            "/api/v1/auth/sign-up/image",
                            "/api/v1/auth/sign-up/email",
                            "/api/v1/auth/sign-up/code")
                    .permitAll()
                    .anyRequest()  // 나머지 요청들은 모두 인증
                    .authenticated();
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return PasswordEncoderFactories.createDelegatingPasswordEncoder();
        }
    
    }

     

    설정 파일 별로 필터 목록을 갖게 된 후, 이 필터들은 WebSecurity 클래스에 전달됨

    WebSecurity는 각각 설정 클래스로부터 필터 목록을 받아서

    FilterChainProxy에 생성자의 인자로 전달함

     

    FilterChainProxy는 설정 클래스 별로 필터 목록을 가지게 됨


    실행 과정

     

    사용자가 요청을 하면

    DelagatingFilterProxy가 먼저 요청을 받고,

    FilterChainProxy에게 요청을 위임함

     

    DelegatingFilterProxy는 서블릿 필터이며 요청을 위임할 때 "springSecurityFilterChain"이라는 이름을 가진 Bean을 찾게 되는데, 그 Bean이 바로 FilterChainProxy임

     

    위임받은 요청을 가지고 있는 각각의 FIlter들에게 순서대로 요청을 맡김

    각각의 필터들이 체인으로 연결되어 수행 → 넘김 → 수행 → 넘김을 반복하는 형태

    이 때, 수행되는 메서드가 doFilter이다

     


     

    FilterChain

     

    저렇게 다양하지만 나는 일단 필요한 필터만 보겠음

     

    UsernamePasswordAuthenticationFilter

    ID, PW를 사용하는 실제 Form 기반 인증을 처리

     

     

    1. 사용자가 입력한 사용자 정보를 가지고 인증 요청

    2. AuthenticationFilter가 이를 가로채 UsernamePasswordAuthenticationToken (인증용 객체, 이하 UPAT)를 생성함

    3. 필터는 요청을 처리하고 AuthenticationManager의 구현체 ProviderManager에 Authentication과 UPAT를 전달함

    4. AuthenticationManager는 검증을 위해 AuthentcationProvider에게 Authentication과 UPAT를 전달함

    5. DB의 사용자 정보와 넘겨받은 사용자 정보를 비교하기 위해 UserDetailsService에 사용자 정보를 전달함

    6. DB에서 찾은 사용자 정보인 UserDetails 객체를 만듦

    7. AuthentcationProvider는 UserDetails를 넘겨받고 UPAT와 비교함

    8. 인증이 완료되면 권한과 사용자 정보를 담은 Authentication 객체가 반환됨

    9. AuthenticationFilter까지 Authentication 객체를 전달함

    10. Authentication을 SecurityContextHolder 세션 영역에 있는 SecurityContext에 저장함

    댓글