SpringSecurity - 로그인 인증 구조

Jeong·2023년 9월 27일
0
post-custom-banner

SpringSecurity

spring security는 servlet filter및 aop기반이므로 장점이 비침투적이라는 것이다. 즉, 개발자가 짠 코드에 변경한다거나 구현한다거 삽입한다거나 할 필요가 없음

  • SecurityContext

    • Authentication 을 보관하는 역할로 SecurityContext를 통해 Authentication 객체를 꺼내올 수 있음
    • Authentication 은getter/setter 뿐
  • SpringContextHolder

    • SecurityContextHolder는 보안 주체의 세부 정보를 포함하여 응용 프로그램의 현재 보안 컨텍스트에 대한 세부 정보가 저장됩니다.
  • UsernamePasswordAuthenticationToken

    • Authentication을 implements한 AbstractAuthenticationToken의 하위 클래스로 username이 Principal의 역할을 하고, password가 Credential의 역할을 합니다.
    • 첫번째 생성자는 인증 전의 객체를 생성하고, 두번째 생성자는 인증이 완료된 객체를 생성해줍니다.
      public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
          // 주로 사용자의 username에 해당함
          private final Object principal;
          // 주로 사용자의 password에 해당함
          private Object credentials;
          
          // 인증 완료 전의 객체 생성
          public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
      		super(null);
      		this.principal = principal;
      		this.credentials = credentials;
      		setAuthenticated(false);
      	}
          
          // 인증 완료 후의 객체 생성
          public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
      			Collection<? extends GrantedAuthority> authorities) {
      		super(authorities);
      		this.principal = principal;
      		this.credentials = credentials;
      		super.setAuthenticated(true); // must use super, as we override
      	}
      }
  • ProviderManager

    • AuthenticationManager 기본 구현
    • AuthenticationProvider(s)로 위임
  • AuthenticationProvider

    • 실제 인증에 대한 부분을 처리하는데, 인증 전의 Authentication 객체를 받아서 인증이 완료된 객체를 반환하는 역할을 합니다.
    • DaoAuthenticationProvider
      • AuthenticationProvider 구현체
      • UserDetailsService를 user DAO로 사용
  • AuthenticationManager

    • 인증에 대한 부분은 AuthenticationManager를 통해서 처리하게 되는데, 실질적으로는 AuthenticationManager에 등록된 AuthenticationProvider에 의해 처리됩니다.

    • 인증이 성공하면 isAuthenticated=true 인 객체를 생성하여 SecurityContext에 저장합니다.

    • 실패할 경우에는 AuthenticationException을 발생시킵니다.

    • DaoAuthenticationProvider는 AbstractUserDetailsAuthenticationProvider를 상속받아 실제 인증 과정에 대한 로직을 처리합니다.

    • AuthenticationManager에 DaoAuthenticationProvider를 등록하는 방법은 WebSecurityConfigurerAdapter를 상속해 만든 ApplicationSecurityConfig에서 할수 있습니다.

      @Configuration
      @EnableWebSecurity
      public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
      
        private final PasswordEncoder passwordEncoder;
      
        @Autowired
        public ApplicationSecurityConfig(PasswordEncoder passwordEncoder,) {
          this.passwordEncoder = passwordEncoder;
        }
      
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
          auth.authenticationProvider(daoAuthenticationProvider());
        }
      
        @Bean
        public DaoAuthenticationProvider daoAuthenticationProvider() {
          DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
          provider.setPasswordEncoder(passwordEncoder);
          provider.setUserDetailsService(applicationUserService);
      
          return provider;
        }
      }
  • UserDetails

    • 인증에 성공하여 생성된 UserDetails 객체는 UsernamePasswordAuthenticationToken을 생성하기 위해 사용됩니다.
    • UserDetails 인터페이스의 경우 직접 개발한 CustomUserDetails에 UserDetails를 implements하여 사용하면 됩니다
  • UserDetailsService

    • UserDetails 객체를 반환하는 단 하나의 메소드를 가지고 있는데, 일반적으로 이를 구현한 클래스의 내부에 UserRepository를 주입받아 DB에 연결하여 처리합니다.
  • GrantedAuthority

    • 현재 사용자(Principal)가 가지고 있는 권한들입니다.
    • 보통 ROLE_ADMINROLE_USER와 같이 ROLE_의 형태로 사용됩니다.
  • Reference

SpringSecurityFilter

  • Spring Security의 서블릿 필터

    • DelegatingFilterProxy 를 이용

    • DelegatingFilterProxy 란?

      • 지정된 이름의 bean으로 서블릿 필터 처리 위임
    • Spring Security에서 DelegatingFilterProxy에 설정하는 서블릿 필터 bean

      • 이름
        • springSecurityFilterChain
      • 타입
        • org.springframework.security.web.FilterChainProxy
  • FilterChainProxy

    • 여러 보안 필터 체인의 리스트 형태로 구성된 SecurityFilterChain들로 처리를 위임

    public class FilterChainProxy extends GenericFilterBean {
        private List<SecurityFilterChain> filterChains;

        // ...
    }
  • 주요 보안 필터들
    • SecurityContextPersistenceFilter
      • SecurityContext 객체를 SecurityContextHolder에 저장
        • 어디에 저장? SecurityContextRepository (default: HttpSession)
      • 요청 처리가 끝나면 제거
    • ConcurrentSessionFilter
      • 현재 Session 유효 여부 파악하여 유효하지 않은 세션에 대한 후처리
      • SessionManagementFilter와 연동 처리
    • UsernamePasswordAuthenticationFilter
      • 특정 URL에서 username, password를 통한 인증 프로세스 진행
      • 인증 처리는 AuthenticationManager에게 위임
      • 인증 성공 처리 (SuccessHandler)
      • 인증 실패 처리 (FailureHandler)
    • RequestCacheAwareFilter
      • 인증 성공 후 기존 요청을 찾아가기 위해 기존 요청을 저장
        • 어디에 저장? RequestCache (default: HttpSession)
          • session attribute : SPRING_SECURITY_SAVED_REQUEST
    • SessionManagementFilter
      • 세션 타임아웃, 동시 접근 제어 등을 처리
    • AuthorizationFilter
      • 권한 프로세스를 처리하는 Filter
      • <intercept-url /> 내용을 기준으로 권한 처리

로그인 인증 구조

  1. 유저가 로그인을 시도, http 요청이 들어옴

  2. Authentication Filter가 http 서버를 request해서 사용자가 보낸 정보를 인터셉트 해 username,password를 조합하여 UsernamePasswordAuthenticationToken을 생성

    • UsernamePasswordAuthenticationTokenAuthentication을 implement한 구현체임
  3. UsernamePasswordAuthenticationToken을 인증을 담당할 AuthenticationManager에게 만들어서 위임시킴

    • AuthenticationManager 동작 과정
    1. 인증 성공시 인증을 AuthenticationProviderAuthentication객체를 전달
    2. UserDetailsService에서 Authentication을 가지고 DB를 조회 일치 시 UserDetails객체를 꺼내서 UserSession을 생성
    3. 위의 과정을 통해 가져온 UserDetailsSecurityContextHolder에 저장, userSessionId와 함께 응답을 보냄
    4. 이후 요청에서 요청쿠키에 UserSessionId를 검증 후 유효하다면 인증을 하게 됨
profile
화이팅!!
post-custom-banner

0개의 댓글