[스프링(Spring)] 시큐리티(Security) 기초

allnight5·2022년 12월 15일
0

스프링

목록 보기
13/62

시큐리티의 구조 참조사이트
시큐리티의 기초 참조사이트
시큐리티 예시 참조사이트

스프링 시큐리티 사용 가능버전

스프링 부트 2.7이상부터 사용이 가능하다.

스프링 시큐리티

인증자체가 비즈니스로직처럼 매번 개발하는 부분이 아니며 익숙하지 않고 팀내에서 이미 개발되어 있는 경우에는신규 프로젝트 할때 이외엔 볼일도 별로 없는 부분이라고 하지만 개발하는 경우도 있을수 있으니 알고 있어야 한다고 한다.

스프링시큐리티의 동작 구조를 이해하면 설정과 추가적인 구현 및 변경이 어느 부분에 적용되어야 되는지 파악이 빨라 집니다.

스프링시큐리티의 동작 구조

스프링시큐리티는 각각의 역할에 맞는 작업을 처리하는 여러개의 필터들이 체인형태로 구성되어 순서에 따라 순차적으로 수행됩니다.

그 중 UsernamePasswordAuthenticationFilter가 인증처리를 담당하고 있습니다.

[그림1] 스프링시큐리티 동작구조

맨위에 시큐리티의 구조 참조사이트에서 가져왔다. 자세히 보고 싶으면 이 그림을 클릭해서 그림으로 이동을 잘몰라서.. 잘라왔다.


아래로 내려가서 읽기전에 가져온곳에서 감사히 한글을 써두셨으니 영어좀 해석하면서 읽어서 이런식으로 동작하는구나라는 순서는 읽고 넘어는것이 좋다.


1. 스프링 시큐리티 작동방식 순서 요약된거

  1. 로그인정보를 담아 서버에 인증을 요청한다.
    SecutiryContext

    1: doFilter(request: HttpServletRequest, response: HttpServletResponse)

브라우저의 로그인화면에서 아이디와 비번을 입력하고 확인을 누르면 서버에 로그인 인증 요청을 하게 되고 스프링시큐리티에 Chain형태로 구성된 Filter들의 doFilter메소드들이 순서에 따라 호출되어 각각의 역할로직들이 수행되게 됩니다.

  1. 인증 처리 담당하는 UsernamePasswordAuthenticationFilter가 실행된다.

    2: attemptAuthentication(request: HttpServletRequest, response: HttpServletResponse):Authentication
    For-login 기반일때 인증된 것이 들어온다면 다음으로 넘어가지만 인증되지 않았다면 로그인 페이지로 변환하게 되는형태 이 다.

  • AbstractAuthenticationProcessingFilter 추상 클래스의 추상메소드 attemptAuthentication를 호출하여 요청을 처리하게 됩니다. attemptAuthentication추상메소드의 구현은 상속한 UsernamePasswordAuthenticationFilter에 구현 되어 있습니다.
  • 추후 외부인증을 위한 작업을 할때 UsernamePasswordAuthenticationFilter기능을 대신하는 커스텀 필터를 추가하게 됩니다.
  • 인증 성공 실패에 따라 AuthenticationSuccessHandler, AuthenticationFailureHandler 를 최종적으로 호출하게 됩니다.
  • 인증이 성공했다면 리턴값 UsernamePasswordAuthenticationToken를 세션에 저장합니다
  1. AuthenticationManager가 적절한 AuthenticationProvider를 찾는다.
    3: authenticate(authRequest):Authentication
    AuthenticationManager는 인터페이스이며 구현체는 ProviderManager입니다. ProviderManager 는 실제 인증을 처리하는 로직이 포함된 AuthenticationProvider 인터페이스의 구현체들 중에 설정된 인증 처리방식의 구현체를 찾아 실행합니다.

  2. 실제 인증처리하는 AuthenticationProvider의 인증처리 메소드를 호출한다.
    4: authenticate(authRequest):Authentication
    일반적으로 클라이언트에서 아이디 비번을 받아 인증하는 방식을 사용한다면 AuthenticationProvider 인터페이스의 구현체 AbstractUserDetailsAuthenticationProvider 추상클래스를 호출하게 되고 실제 상속한 클래스의 DaoAuthenticationProvider에서 인증 처리를 하게 됩니다.

  3. 인증제공자는 UserDetailsService를 호출하여 사용자를 가져온다.
    5: loadUserByUsername(username:String):UserDetails
    개발자는 UserDetailsService 인터페이스를 구현해야합니다. UserDetailsService의 구현체에는 일반적으로 회원정보가 DB에 있다고 한다면 사용자의 이름(ID)로 DB를 조회하여 비밀번호가 일치하는지 확인하여 인증을 처리합니다. 인증이 완료되면 UsernamePasswordAuthenticationToken에 회원정보를 담아 리턴하게 됩니다.

2. Spring Security 주요 컴포넌트 확인하기

  • Spring Security 와 Filter Spring Security는 요청이 들어오면 Servlet FilterChain을 자동으로 구성한 후 거치게 한다. FilterChain은 여러 Filter를 chain형태로 묶어놓은 것을 의미합니다. 여기서 Filter 란, 톰캣과 같은 웹 컨테이너에서 관리되는 서블릿의 기술이다. Filter는 Client 요청이 전달되기 전후의 URL 패턴에 맞는 모든 요청에 필터링을 해준다. CSRF, XSS 등의 보안 검사를 통해 올바른 요청이 아닐 경우 이를 차단해 준다. 따라서 Spring Security는 이런한 기능을 활용하기위해 Filter를 사용하여 인증/인가를 구현하고 있다.
  • SecurityFilterChain Spring 의 보안 Filter를 결정하는데 사용되는 Filter session, jwt 등의 인증방식들을 사용하는데에 필요한 설정을 완전히 분리할 수 있는 환경을 제공한다. 아래는 Security Filter 들의 실행 순서입니다. 우선적으로 우리는 여기서 UsernamePasswordAuthenticationFilter 만 한번 눈으로 확인하고 넘어가면 되겠습니다.
  • AbstractAuthenticationProcessingFilter
    • 사용자의 credential을 인증하기 위한 베이스 Filter
  • UsernamePasswordAuthenticationFilter UsernamePasswordAuthenticationFilter 는 AbstractAuthenticationProcessingFilter를 상속한 Filter다. 기본적으로 아래와 같은 Form Login 기반을 사용할 때 username 과 password 확인하여 인증한다. Form Login 기반은 인증이 필요한 URL 요청이 들어왔을 때 인증이 되지 않았다면 로그인페이지를 반환하는 형태이다.
  • SecurityContextHolder
    • SecurityContextHolder 에는 스프링 시큐리티로 인증을 한 사용자의 상세 정보를 저장한다.

    • SecurityContext 란? SecurityContextHolder 로 접근할 수 있으며 Authentication 객체를 가지고 있다.

      // 예시코드
      SecurityContext context = SecurityContextHolder.createEmptyContext();
      Authentication authentication = new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
      context.setAuthentication(authentication);
      
      SecurityContextHolder.setContext(context);
  • Authentication
    • 현재 인증된 사용자를 나타내며 SecurityContext 에서 가져올 수 있다.

    • principal : 사용자를 식별한다. Username/Password 방식으로 인증할 때 보통 UserDetails 인스턴스다.

    • credentials : 주로 비밀번호, 대부분 사용자 인증에 사용하고 다음 비운다.

    • authorities : 사용자에게 부여한 권한을 GrantedAuthority 로 추상화하여 사용한다.

      		<UserDetails>
      		@Override
          public Collection<? extends GrantedAuthority> getAuthorities() {
              UserRoleEnum role = user.getRole();
              String authority = role.getAuthority();
              System.out.println("authority = " + authority);
      
              SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(authority);
              Collection<GrantedAuthority> authorities = new ArrayList<>();
              authorities.add(simpleGrantedAuthority);
      
              return authorities;
          }
      
      Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

      UsernamePasswordAuthenticationToken는 Authentication을 implements한 AbstractAuthenticationToken의 하위 클래스로, 인증객체를 만드는데 사용된다.

  • UserDetailsService UserDetailsService는 username/password 인증방식을 사용할 때 사용자를 조회하고 검증한 후 UserDetails를 반환한다. Custom하여 Bean으로 등록 후 사용 가능하다.
  • UserDetails
profile
공부기록하기

0개의 댓글