본문 바로가기
Web/Spring-Security

[Security] 시큐리티 파헤치기 (4) : 인증이란? (feat. Authentication)

by 희조당 2023. 8. 17.
728x90

🙋 들어가며

이번 글부터 시큐리티의 인증 시리즈를 다뤄볼 생각입니다.

인증에 대해서 무엇인지 알아보면서 인증 시리즈를 시작해 보겠습니다.

또한, 어떤 객체에 인증 정보를 담을지까지 알아보겠습니다.


🙆‍♂️ 인증(Authentication)?

인증이란, 어떤 사용자가 접근하고 있는지 확인하는 절차입니다.

보안에 민감한 정보를 다룬다면 당연히 누가 사용하는지 확인하고 접근시켜야 합니다.

 

자세하게 어떻게 동작하는지는 몰라도, 인증하려면 정보를 담아줄 그릇이 필요할 것 같습니다.

바로 이 그릇이 Authentication 객체입니다.

🪙 Authentication 인터페이스

Authentication 인터페이스는 인증 정보를 담는 하나의 토큰입니다.

실제 코드는 다음과 같이 구현되어 있습니다.

public interface Authentication extends Principal, Serializable {
    // 인증 대상의 권한 모음
    Collection<? extends GrantedAuthority> getAuthorities();

    // 인증 키
    Object getCredentials();

    // 요청에 대한 추가정보
    Object getDetails();

    // 유저 식별자
    Object getPrincipal();

    // 인증 완료 여부
    boolean isAuthenticated();

    // 인증 완로 여부 setter, false를 반환해야 한다 (명세)
    void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}

 

Authentication 인터페이스는 다양한 구현체를 제공하고 있습니다.

나중에 자세히 알아보겠지만 기본적으로 UsernamePasswordAuthenticationToken을 사용합니다.

그림 1 : 다양한 Authentication 구현체들

🤷‍♂️ 언제 사용할까?

시큐리티에서는 Authentication를 두 가지 목적으로 구현했습니다.

🔒 인증 요청 대상

실질적으로 시큐리티에서 AuthenticationManager 인터페이스가 인증을 수행합니다.

AuthenticationManager는 단 하나의 메서드만 가지는데 Authentication를 매개 변수로 받습니다.

이 흐름에서는 인증 전의 Authentication을 검증하므로 isAuthenticated()가 false를 리턴합니다.

public interface AuthenticationManager {
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
}

🔓 인증된 사용자

AuthenticationManager를 통해서 인증을 통과한 뒤에 인증된 사용자 정보를 나타낼 때 사용합니다.

SecurityContext로부터 인증된 사용자의 정보를 가져올 수 있습니다.

😋 저장된 정보

Authentication 인터페이스는 인증에 필요한 정보를 담는 그릇입니다.

따라서 다음과 같은 정보를 꼭 포함해야 합니다.

  • Principal : 사용자 식별 정보입니다. Object로 구현되어 다양한 값을 받는다는 점이 핵심입니다.
  • Credentials : 인증에 필요한 키를 의미합니다. 대개 비밀번호입니다.
  • Authorities : 인증 대상에게 부여된 권한을 의미합니다.

😎 인증 전/후

인증 전/후에 따라 Authentication의 값이 어떻게 다른지 디버그로 확인해 보겠습니다.

우선 모든 인증 절차를 받는 AbstractAuthenticationProcessingFilter에 doFilter()를 확인합니다.

그림 2 : AbstractAuthenticationProcessingFilter에서 인증을 시작

 

attemptAuthentication()는 추상 메서드로 실제 구현체의 도움을 받아서 인증을 진행합니다.

그림 3 : 추상 메서드인 attemptAuthentication()

 

현재 로그인에 대한 어떠한 설정이 없기 때문에 기본으로 제공하는 Form 인증 방식을 사용합니다.

따라서, 실제 구현체는 UsernamePasswordAuthenticationFilter입니다.

 

이때 들어오는 값을 확인하면 principal에 문자열이 들어왔습니다.

그리고 예상처럼 인증 전에는 authenticated이 false인 것을 확인할 수 있습니다.

그림 4 : UsernamePasswordAuthenticationFilter에 넘어온 Authentication 객체

 

이후 정상적으로 인증을 마치고 돌아가면 다음과 principal이전과 다른 타입이 들어옵니다.

User는 시큐리티에서 제공하는 사용자의 인증 정보와 권한 정보를 가진 객체입니다.

이 외에 authoritiesauthenticated를 확인해 보면 인증이 잘 마무리된 것을 확인할 수 있습니다.

그림 5 : 인증을 마친 뒤의 Authentication 객체

이렇게 해서 인증 전/후에 어떻게 Authentication 객체가 변화하는지 알아보면서

왜 principal은 Object 타입을 쓰는지까지 알아보았습니다 😋😋


😜 정리

  • 인증은 누가 프로그램에 접근하는지 확인하는 절차이다.
  • 인증 정보를 담는 객체가 Authentication이다.
  • Authentication은 인증하기 위해서, 인증 정보를 표현하기 위해서 사용한다.
  • principal은 Object로 다양한 정보를 담도록 구현되어 있다.

-Reference:

https://docs.spring.io/spring-security/reference/servlet/authentication/architecture.html

 

😋 지극히 개인적인 블로그지만 댓글과 조언은 제 성장에 도움이 됩니다 😋

댓글