Spring Security Trivia

susu·2023년 2월 20일
0
post-thumbnail

GDSC Sookmyung에서 Spring Security를 주제로 10분 세미나를 준비하게 되었습니다.
오탈자나 잘못된 정보가 있을 수 있으니 언제든지 제게 알려주세요!

Trivia?

한국어로 하찮은 사실들, 여담이라는 의미를 가지고 있다.

얼마 전 캐나다에 어학연수를 다녀왔는데,
영어권 사람들은 이 Trivia라는 것을 굉장히 좋아한다고 느꼈다.
재밌을 것 같아서 주제로 가져와보면 어떨까 싶은 생각이 들었다.

Spring Security

스프링의 큰 장점 중 하나는 고수준의 추상화이다.
즉, 내부에는 복잡한 로직이 있지만 우리는 그걸 일일이 다 알 필요가 없다.
그런 스프링의 장점이 많이 녹아있는 프레임워크 중 하나가 바로 스프링 시큐리티다.

스프링 시큐리티란 스프링 애플리케이션을 보호하기 위해 스프링에서 제공하는 보안 표준이다.
스프링을 써본 사람이라면 아마 소셜 로그인이나 토큰 로직을 통해서 이미 접해봤을 확률이 높다.

본인 또한 소셜 로그인을 통해 스프링 시큐리티에 관심을 갖게 됐다.
보안 분야에 관심은 많은데 직접 공부하기에는 양이 너무나 방대했다.
하지만 스프링 시큐리티를 이용하면 종속성 몇 줄 추가로 높은 수준의 보안을 구현할 수 있다.
이러한 점에 매료되어 관심을 가지게 되었다.

🌽 Trivia 1. 스프링 시큐리티의 원래 이름은 Acegi Security였다

스프링 시큐리티, 그러니까 ACEGI 시큐리티를 만든 벤 알렉스에 의하면,
2003년 11월에 이 프레임워크를 만들고 압축해서 로드 존슨과 융겐 휄러에게 보여주고
스프링 시큐리티라는 이름을 제안했다고 한다.

하지만 두 사람이 당시 다 너무 빴던 탓에 제대로 검토를 못하고
그냥 ACEGI 시큐리티라는 이름을 붙여 버리면서 Acegi라는 이름을 먼저 얻게 되었다.
(*ACEGI는 그냥 알파벳 홀수번째 키를 누른 것이다. 별 뜻은 없었다.)
하지만 이후에 정식으로 스프링 커뮤니티로 들어오게 되면서 우리가 아는 스프링 시큐리티라는 이름을 가지게 되었다.

인증 = Authentication

스프링 시큐리티의 기본적인 동작 구조는 크게 인증인가 단계로 나눌 수 있다.
로그인과 같은 요청이 오면 인증을 통해 이 사용자가 누구인지 확인하고,
인증에 성공하면 특정 자원에 접근할 수 있는 사람인지 확인해서 접근 권한을 부여하는 구조이다.
접근 권한을 부여한다, 인가, Authorization 모두 같은 의미로 생각할 수 있다.

그렇다면 스프링 시큐리티로는 과연 어떤 요청이 들어갈까?

흔히 아이디와 비밀번호에 기반한 요청을 로그인이라 한다.
그런데 이 로그인 요청에 대한 인증 방식에도 여러가지가 있다.
크게 세션쿠키를 이용한 방식, JWT 발급 방식, OAuth로 나눌 수 있는데,
스프링 시큐리티의 기본적인 동작 원리는 세션과 쿠키 방식을 채택하고 있다.
사용자의 인증 정보가 담긴 객체를 세션으로 DB에 저장해두고,
이 세션으로는 사용자 개개인을 식별할 수 없으니 식별자는 쿠키에 따로 저장하는 방식이다.
이 방식은 서버가 클라이언트의 상태를 저장하는, 일종의 상태를 갖는다고 볼 수 있다.

상태를 저장한다는 측면에서 보면 JWT는 세션과 양극단에 서있다고 볼 수 있다.
세션과는 달리 무상태성을 가지기 때문이다.
서버가 인증 정보를 담은 이 토큰을 저장하고 발행하지만,
복호화 과정 없이는 클라이언트의 정보를 알 수가 없다.

🌽 Trivia 2. 로그인 방식에도 궁합이 있다

물론 이게 정석이라는 건 아니지만,
로그인 방식마다 서로 그 특성이 잘 어울리는 프레임워크들이 있다.

먼저 세션과 쿠키 방식은 세션을 DB에 저장한다는 특징이 있다.
이런 경우 서버와 클라이언트가 강하게 결합해있는 서버사이드 렌더링 프레임워크(SSR)들과 궁합이 맞는다.

하지만 웹 개발에 있어 최근의 유행은 서버와 클라이언트가 RESTful하게 소통하는 것이다.
렌더링 주도권이 클라이언트 쪽에 있는 프레임워크들,
즉 CSR 프레임워크들로 개발을 하려면 서버랑 클라이언트가 완전히 분리돼야 한다.
그래서 이 인증 정보가 상태를 가지면 안되는거고,
그게 무상태성을 가진 JWT가 CSR 엔진을 가진 프레임워크랑 궁합이 잘 맞는 이유이다.

인증 객체 (Authentication Object)

먼저 인증의 요청부터 인증된 컨텍스트를 담기까지.
그 모든 과정의 주인공인 인증 객체에 대해 알아야 한다.

Authentication, 즉 인증 객체란 당신이 누구인지를 증명하기 위해 필요한 정보들을 담은 객체이다.
보통 인증 시에 필요한 아이디와 패스워드를 담고 있는 일종의 토큰이라 볼 수 있다.

인증 과정에서 이 정보들은 인증 객체에 담겨서 떠다니다가,
인증이 완료되면 그 최종 결과를 담아서 SecurityContext라는 또 다른 객체에 저장된다.

이 객체가 가질 수 있는 인증 정보들로는 다음과 같다.

  • principle : 사용자 아이디나 사용자 객체
  • credential : 사용자 비밀번호
  • authorities : 인증된 사용자가 가질 수 있는 권한 리스트
  • details : 인증 부가정보
  • authenticated : 인증 여부

🌽 Trivia 3. SecurityContextHolder의 목적은 Thread 공유

전부터 스프링 시큐리티를 볼 때마다 궁금했던게,
왜 저렇게 인증객체를 겹겹이 감싸는 걸까? 하는 거였다.
그래서 이번에 제대로 알아보고 싶어서 찾아본 내용이다.

일단 스프링 시큐리티는 모든 요청에 대해 스레드를 할당한다.
그리고 그 요청의 인증 정보를 전역으로 뿌리기 위해서,
인증 객체를 담은 SecurityContext를 메인 쓰레드랑 하위 쓰레드로 나눠서 관리한다고 한다.
그런데 쓰레드가 여러 단계로 갈리니까, 이 쓰레드를 전역으로 관리하기가 어려워진다.
그래서 SecurityContextHolder라는 껍질을 하나 더 씌워서 쓰레드를 공유할 수 있는 레벨을 지정하게 한 것이다.

지정 가능한 공유 레벨은 세 가지가 있다.

  • MODE_THREADLOCAL : 로컬 스레드끼리만 공유
  • MODE_INHERITABLETHREADLOCAL : 로컬 스레드의 하위 스레드까지만 공유
  • MODE_GLOCAL : 어플리케이션 내 전역 공유

전체 인증 과정 요약

전체 인증 과정을 간단하게 요약해보았다.

profile
블로그 이사했습니다 ✈ https://jennairlines.tistory.com

0개의 댓글