[Spring Security] 기본 개념

in_ho_·2023년 10월 22일
0

Spring Security

목록 보기
1/2
post-thumbnail

1. 필요성

  • 애플리케이션을 개발할 때 인증인가 등의 보안 기능을 추가해야 할 때가 있습니다.

2. 인증, authentication

  • 사용자가 누구인지 확인하는 단계
  • 인증의 대표적인 예로 로그인이 있습니다.

    로그인

    • 로그인은 데이터베이스에 등록된 아이디와 패스워드를 사용자가 입력한 아이디와 비밀번호와 비교해서 일치 여부를 확인하는 과정입니다.
  • 로그인을 성공하면 애플리케이션 서버는 응답으로 사용자에게 토큰을 전달합니다.
  • 로그인에 실패한 사용자는 토크늘 전달받지 못해 원하는 리소스에 접근할 수 없게 됩니다.

3. 인가, authorization

  • 인증을 통해 검증된 사용자가 애플리케이션 내부의 리소스에 접근할 때 접근할 권리가 있는지를 확인하는 과정
  • 일반적으로 사용자가 인증하는 단계에서 발급받은 토큰은 인가 내용을 포함하고 있습니다.

4. 접근 주체, principal

  • 애플리케이션의 기능을 사용하는 주체
  • 접근 주체는 사용자가 될 수도 있고, 디바이스, 시스템 등이 될 수도 있습니다.
  • 애플리케이션은 인증을 통해 접근 주체를 신뢰할 수 있는지 확인하고, 인가를 통해 접근 주체에게 부여진 권한을 확인합니다.

5. Spring Security

  • 애플리케이션의 인증, 인가 등의 보안 기능을 제공하는 스프링 하위 프로젝트입니다.

5-1. Spring Security의 동작 구조

  • 스프링 시큐리티는 서블릿 필터(Servlet Filter)를 기반으로 동작하며 DispatcherServlet 앞에 필터가 배치되어 있습니다.
  • Filter Chain은 서블릿 컨테이너에서 관리하는 ApplicationFilterChain을 의미합니다.
  • 클라이언트에서 요청을 보내면 서블릿 컨테이너는 URI를 확인해서 필터와 서블릿을 매핑합니다.
  • Spring Security는 필터 체인을 서블릿 컨테이너의 필터 사이에서 동작시키기 위해 DelegatingFilterProxy를 사용합니다.
  • DelegatingFilterProxy는 서블릿 컨테이너의 생명주기와 스프링 애플리케이션 컨텍스트 사이에서 다리 역할을 수행하는 필터 구현체입니다.
  • DelegatingFilterProxy는 표준 서블릿 필터를 구현하고 있으며, 역할을 위임할 필터체인 프록시(FilterChainProxy)를 내부에 가지고 있습니다.

    필터체인 프록시는 스프링 부트의 자동 설정에 의해 생성됩니다.
    필터체인 프록시 = 스프링 시큐리티에서 제공하는 필터
    필터체인 프록시에서 사용할 수 있는 보안 필터 체인은 List 형식으로 담을 수 있게 설정돼 있어 선택하여 지정할 수 있습니다.

  • 보안 필터체인은 WebSecurityConfigurerAdapter 클래스를 상속받아 설정할 수 있습니다.(여러 보안 필터체인을 만들기 위해서는 상속받는 클래스를 여러 개 생성하면 됩니다.)

    여러 개의 상속 클래스를 구현할 경우 @Order 어노테아션을 이용하여 우선 순위를 지정해야 합니다.(하지 않을 경우 예외 발생)
    현재는 해당 클래스가 DEPRECATED됨

5-2. UsernamePasswordAuthenticationFilter

  • 별도의 설정이 없을 경우 스프링 시큐리티에서는 SecuriryFilterChain에서 필터 중 UsernamePasswordAuthenticationFilter를 통해 인증을 처리합니다.

5-2-1. UsernamePasswordAuthenticationFilter를 통한 인증 과정

Notion으로 해당 과정을 그리다 보니 화살표가 복잡하게 보이긴 한다...!

  1. HTTP 요청이 들어오면 서블릿 필터에서 SecurityFilterChain으로 작업이 위임되고 그 중 AuthenticationFileter에서 인증을 처리합니다.

    여기서는 AuthenticationFilter는 UsernamepasswordAuthenticationFilter입니다.

  2. AuthenticationFilter는 요청 객체(HttpServletRequest)에서 username과 password를 추출해서 토큰을 생성합니다.
  3. AuthenticationManager에게 토큰을 전달합니다.

    AuthenticationManager는 인터페이스이며, 일반적으로 사용되는 구현체는 ProviderManager입니다.

  4. ProviderManager는 인증을 위해 AuthenticationProvider로 토큰을 전달합니다.
  5. AuthenticationProvider는 토큰의 정보를 UserDetailsService에 전달합니다.
  6. UserDetailsService는 UserDetails 객체를 생성합니다.(데이터베이스 조회)
  7. 생성된 UserDetails 객체는 AuthenticationProvider로 전달되며, 해당 Provider로인증을 수행하고 성공하게 되면 ProviderManager로 권한을 담은 토큰을 전달합니다.
  8. ProviderManager는 검증된 토큰을 AuthenticationFilter로 전달합니다.
  9. AuthenticationFilter는 검증된 토큰을 SecurityContextHolder에 있는 SecurityContext에 저장합니다.
  • 위에 있는 UsernamePasswordAuthenticationFilter는 접근 권한을 확인하고 인증 실패할 경우 로그인 폼이라는 화면을 보내는 역할을 수행합니다.

    Rest API일 경우 이를 사용하지 않고 JWT 토큰을 사용합니다. 그러므로 JWT와 관련된 필터를 생성하고 UsernamePasswordAuthenticationFilter 앞에 먼저 배치해서 먼저 인증을 수행할 수 있게 설정해야합니다.

5-3. JWT

  • JSON Web Token는 당사자 간에 정보를 JSON 형태로 안전하게 전송하기 위한 토큰
  • JWT는 URL로 이용할 수 있는 문자열로만 구성돼 있으며, 디지털 서명이 적용돼 있어 신뢰할 수 있습니다.

    URL에서 사용할 수 있는 문자열로 구성돼 있기 때문에 HTTP 구성요소 어디든 위치가 가능하다.

  • JWT는 주로 서버와의 통신에서 권한 인가를 위해 사용됩니다.

5-3-1. JWT 구조

헤더.내용.서명
  • 헤더
    • 검증과 관련된 내용
    {
      “alg": "HS256",
      "typ": "JWT"
     }
    • alg 속성에는 해싱 알고리즘을 지정합니다.
      • 해싱 알고리즘은 보통 SHA256 또는 RSA를 사용합니다.
    • typ 속성에는 토큰의 타입으로 지정합니다.
    • 이렇게 완성된 헤더는 Base64Url 형식으로 인코딩 됩니다.
  • 내용
    • 이곳에 포함된 속성들을 클레임(Claim)이라고 합니다.
      1. 등록된 클레임(Registered Claims)
      2. 공개 클레임(Public Claims)
      3. 비공개 클레임(Private Claims)
    • iss : JWT의 발급자 주체
    • sub : JWT의 제목
    • aud : JWT의 수신인
    • exp : JWT의 만료시간
    • nbf : Not Before
    • iat : JWT가 발급된 시간
    • jtl : JWT의 식별자 ID
  • 서명
    • 인코딩된 헤더, 인코딩된 내용, 비밀키, 헤더의 알고리즘 속성값을 가져와 생성합니다.

0개의 댓글