본문 바로가기

DEVELOPER/Spring & JPA

[스프링 시큐리티] 비인증 사용자를 위한 '익명 사용자' 알아보기

안녕하세요😎 백엔드 개발자 제임스입니다 :) 

오늘 포스팅할 내용은 스프링 시큐리티와 관련된 내용입니다. 제가 프로젝트를 진행하면서 인증과 관련된 기능을 구현하던 중이었습니다. 해당 기능의 요구사항은 인증된 회원과 비인증 회원에게 서로 다른 데이터를 제공하는 역할을 하는 것이었습니다. 따라서 Security Context Holder에 인증 정보가 있는지 체크를 해야 했습니다.

여기서 저는 비인증 회원이라면, Security Context에 당연히 인증 정보가 없을 것이라고 이분법적인 사고를 했습니다.

SecurityContextHolder 에 저장된 인증정보를 반환하는 메서드

만약 저의 논리에 따른다면, 비인증 회원의 요청에 해당 메서드는Null을 리턴하겠죠?

하지만 문제는!

SecurityContextHolder 내부 디버깅 과정

Null 체크를 진행한다면, Null 이 아닌 결과가 나옵니다. 제 생각과는 완전히 달랐습니다. 위에 이미지와 같이 anonymousUser(익명 사용자) 라는 정보를 가진, AnonymousAuthenticationToken이 Authentication으로 생성되어 있었습니다.

즉, 비인증 회원들은 익명 사용자로 서버에 접근합니다.

익명 사용자

익명사용자는 문자열 "anonymousUser" 이 저장되어 있는 principal과 ROLE_ANONYMOUS 권한 정보를 가지고 있는 객체입니다. 그리고 해당 객체(토큰)를 생성하고, 처리하는 필터가 AnonymousAuthenticationFilter 입니다.

 

익명 사용자가 별도로 존재하는 이유는 무엇일까?

익명사용자 토큰 생성자를 봤을 때, 인증 정보와 권한 정보가 null 이 아닌 값을 필수로 갖고 있어야 함을 알 수 있습니다.

# 스프링 시큐리티 설계자는 익명 사용자를 도입한 이유가 무엇일까요?
여기서 익명 사용자라는 객체는 SecurityContext 객체에 저장하여 애플리케이션 전역적으로 사용할 수 있도록 도입했을 뿐입니다.
스프링 시큐리티는 익명 사용자 즉 로그인을 하지 않은 상태의 사용자도 별도의 역할 즉 인증정보, 권한정보를 가지도록 설계되었습니다.
물론 인증정보와 권한정보 자체가 정식 인증을 받은 상태가 아닌 익명 사용자용 인증, 권한 정보라고 볼 수 있습니다.
그리고 스프링 시큐리티에서 인증받지 않은 상태를 판별하는 기준은 user 객체의 존재 여부가 아닙니다.
즉, 어떤 정보를 저장하고 있냐를 체크해야 합니다. 

이 말에서 객체지향 프로그래밍을 따른 의도가 있다고 볼 수 있었습니다. 익명 사용자도 또 하나의 객체로 다루면서, 클래스를 통해 비인증 회원들을 관리하려는 목적이 있었음을 알았습니다. 그리고 또 한 가지는 만약 익명 사용자가 아닌 Null이라면, NullPointerException 이 발생할 수 있습니다.

정리하자면, 익명 사용자라고 해서 뭔가 기능이 추가되지는 않습니다. 즉, [어디에도 갈 수 없는 통행증]을 얻은 것이나 다름없습니다.

 

익명 사용자를 만드는 AnonymousAuthenticationFilter (익명 사용자 필터)

AnonymousAuthenticationFilter는 인증받지 않은 사용자를 위해 제공되는 필터입니다. 이 필터는 익명 사용자와 인증 사용자를 구분해서 처리하는 역할을 수행합니다. 

익명 사용자 인증 동작 과정

  1. 요청이 왔을 때, 인증 객체가 있는지 확인합니다.
  2. 인증 객체가 있다면, 인증받은 사용자를 SecurityContext에  넣고, 다음 필터를 진행합니다. 
  3. 인증 객체가 없다면, AnonymousAutenticationToken의 인증 객체를 생성하고 SecurityContextHolder에 저장합니다.

 

반응형