보안

참고
https://www.udemy.com/course/spring-boot-and-spring-framework-korean/learn/lecture

보안

보안과 관련된 두 가지 중요한 기본 요소인 인증과 권한 부여가 있다. 이것은 REST API, 웹 애플리케이션, 데이터베이스, 클라우드 등 다양한 리소스에 존재하며 식별을 위한 ID가 존재한다.
ID는 사용자일 수도 있고 애플리케이션일 수도 있으며, 리소스 접근과 더불어 REST API를 호출하기도 하고 웹 애플리케이션에 로그인, 데이터베이스의 데이터를 읽거나 수정하는 등 여러 가지 작업을 수행한다.

만약 시스템에 보안을 구현하지 않는다면 애플리케이션이나 시스템을 이용할 사용자의 ID를 어떻게 확인해야 할 것이고 액세스는 어떻게 설정해야 할 것인지? 또 사용자가 액세스할 수 있는 리소스와 사용자가 리소스별로 수행할 수 있는 작업은 어떻게 설정해야 할 것인가?

바로 이러한 맥락에서 두 가지 중요한 개념이 필요하다.

첫 번째, 인증

인증의 목적은 접근 대상이 적절한 사용자인지 판단하기 위해 사용자의 ID 정보와 일치하는지 확인하는 것이다.

인증에 사용 가능한 여러 가지 방법 중 한 가지 접근법은 사용자가 기억할 수 있는 정보를 이용하는 것이다. 예를 들어 사용자 ID와 패스워드의 조합 같은 것, 사용자 ID와 패스워드를 이용해 LinkedIn 계정에 로그인하고 YouTube나 Facebook 계정에 로그인하는 것이 그 예이다.

또 다른 인증 옵션은 사용자의 소유물을 이용하는 것으로 지문, 홍채 인식, 모바일 기기에 설치된 앱 등을 사용하는 것이다.
이러한 요소를 여러 개 결합해 인증을 수행하기도 하는데 이를 다단계 인증이라고 한다.
특정 시스템에서 처음으로 Google 계정에 로그인하는 경우가 그 예이다. 사용자 ID와 패스워드로 로그인한 다음 모바일 디바이스로 추가 인증을 받게 된다. 기억하는 정보와 소유물을 함께 이용하는 것이다.

또 하나 중요한 개념은 권한 부여이다. 사용자가 적절한 액세스 권한을 보유했는지를 판단한다. 사용자를 인증한 뒤 사용자의 액세스 권한을 확인하게 된다. 특정 리소스에 대해 특정 작업을 수행할 액세스 권한이 있는지 확인하는 것이다.

어떤 시스템에서든 인증과 권한 부여는 매우 중요하다.
예를 들어 공항에서 비행기에 탑승하려고 할 때, 승객은 여권이나 다른 신분증을 검사받아야 한다. 이것이 인증이다. 반면 권한 부여는 승객이 보유한 항공권 또는 탑승권이다. 여권으로 인증하고 항공권으로 탑승 권한을 부여한다.

보안의 6가지 주요 원칙

첫 번째는 Trust Nothing. 아무것도 신뢰하지 않는 것이다.
무엇도 신뢰하지 않고 들어오는 모든 요청, 데이터를 검증해야 한다.

두 번째는 Asign Least Privileges. 최소 권한만을 할당하는 것이다.
각 사용자에게 필요한 사용자 역할과 액세스 권한을 명확히 정하고 모든 레벨에서 가능한 한 최소한의 권한을 할당해야 한다. 그리하여 데이터베이스, 서버 등, 시스템을 구성하는 모든 요소에 대한 액세스를 최소화해야 한다.
시스템 설계를 시작할 때부터 보안 구조를 구상해야한다.

세 번째는 Have Complete Mediation. 완벽한 조율 구축이다.
반드시 정해진 경로를 통해 자격을 확인받은 후에만 시스템에 접근가능 해야 한다.

네 번째는 Have Defense In Depth 심층적인 방어 구축이다.
애플리케이션을 빌드할 때 여러 레이어를 고려해야 하듯이 보안도 여러 층으로 구축해야 한다. 전송 레이어와 네트워크 레이어, 인프라와 운영 체제 레벨과 애플리케이션 레벨에도 보안을 구현해야 한다.

다섯 번째는 Have Economy Of Mechanism.
보안 아키텍처를 가능한 한 간단하게 유지하는 것이다. 간단한 시스템을 보호하기가 더 쉽다. 즉, 매커니즘의 효율성이 필요하다.

여섯 번째는 Ensure Openness Of Design. 설계의 개방성을 보장하는 것이다.
개방형 보안 설계를 구축하고 개방형 보안 표준을 사용하라. 예를 들면 JWT가 있다. 이러한 원칙을 따른다면 보안 결함을 식별하고 해결하기가 더 수월해진다.

예시

보안 시스템 빌드의 6가지 원칙을 비행기 탑승으로 예를 들자면,
첫 번째, 아무것도 신뢰하지 않고 모든 요청을 검증하는 것.
여권이나 신분증이 없으면 공항에 갈 수 없다. 즉 공항을 이용하는 모든 사람은 인증을 거친다.

두 번째, 최소 권한 할당.
공항을 이용하는 사람은 승무원, 조종사 항공사 탑승 수속 사무원 등 역할에 따라 다른 직위(권한)를 가진다.
모든 사람이 할당된 이상으로 권한을 남용하지 않도록 각 레벨에서 보안 검사를 수행한다.

세 번째, 완벽한 조율.
일반적으로 공항의 입구는 명확하게 정해져 있고 이곳을 통해서만 공항에 들어올 수 있다.
모든 사람이 입구에서 여권, 항공권, 탑승권을 확인받아 인증되고 권한을 부여받는다.
자격을 확인받은 후에만 시스템, 비행기에 들어올 수 있다.

네 번째, 심층적인 방어 구축.
공항에서는 여권과 탑승권을 여러 번 검사한다.
먼저 보안 게이트를 거친 후 보안 검색대에서 검사하고, 탑승 전에 다시 확인한다.
즉 다층적인 보안, 심층적인 방어를 수행하는 것이다.

다섯 번째, 메커니즘의 효율성.
대체로 공항의 보안 절차는 매우 간단해서, 공항을 처음 이용하는 경우에도 모든 보안 절차를 쉽게 준수할 수 있다.

여섯 번째, 설계의 개방성 확보.
일반적으로 전 세계 모든 공항에서 표준 보안 시스템이 적용되고 있다.

Spring Security

Spring 생태계에서 가장 인기 있는 보안 프로젝트는 Spring Security이다.
Spring Security는 웹 애플리케이션, REST API, 마이크로서비스 등을 보호할 수 있다.
관련하여 필터 체인, 인증 관리자, 인증 제공자, JWT 같은 여러 개념이 있는데, 이러한 다양한 개념을 이해해야 보안과 Spring Security를 사용할 수 있다.

먼저 Spring Security의 작동 방식을 보면, Spring으로 웹 애플리케이션이나 REST API를 빌드할 때 백그라운드에서 Spring MVC를 사용한다. 그리고 Spring 웹 애플리케이션으로 들어오는 모든 요청은 가장 먼저 디스패처 서블릿으로 보내진다. 디스패처 서블릿은 요청의 URL, 요청 메서드를 확인한 후 적절한 컨트롤러로 라우팅한다. 즉, 디스패처 서블릿은 프론트 컨트롤러 역할을 한다. 모든 요청을 인터셉트해 적절한 컨트롤러로 라우팅한다.

Request -> Dispatcher Servelet -> Controller

그렇다면 Spring Security는 어떻게 작동될까?
Spring Security는 이 과정 중간에 또 다른 레이어로 추가된다.
디스패처 서블릿으로 들어오는 모든 요청을 Spring Security가 필터 체인을 사용하여 요청을 인터셉트한다.
그리고 Spring Security가 요청의 인증과 권한 부여를 확인하고 나면 요청을 디스패처 서블릿으로 전송하고 그다음 단계인 컨트롤러까지 보내진다.

Request -> Spring Security -> Dispatcher Servelet -> Controller

Spring Security는 요청이 들어오자마자 일련의 필터를 실행하는데, 이것을 Spring Security Filter Chain이라고 한다. Spring Security가 필터 체인을 통해 앞서 설명한 보안 원칙, 완벽한 조율 구축의 방법으로 모든 요청에 대한 인증과 권한 부여를 구현한다. 모든 요청은 Spring Security Filter Chain을 통해 인터셉트된 후 인증과 권한 부여를 위한 확인을 받는다.

이 필터는 다양한 기능을 제공하는데, 기본적인 기능은 인증이다. Spring Security가 지원하는 인증 매커니즘에는 여러 가지가 있는데, 관련된 필터로 인증을 제공한다.

필터의 두 번째 기능은 권한 부여이다.
사용자가 적절한 액세스 권한을 보유했는지 확인하는 것이다. AuthorizationFilter가 그 예이다.

세 번째 기능은 CORS(Cross-Origin Resource Sharing), 오리진 간 리소스 공유를 설정할 수 있다.
풀 스택 애플리케이션을 빌드하는 경우 한 도메인에는 프론트엔드를 다른 도메인에는 백엔드 REST API를 배포할 수 있고, 이런 구조에서 백엔드 REST API는 브라우저에서 실행되는 프론트엔드 애플리케이션으로부터 호출을 받는다. 이것과 관련된 사항을 설정하는 방법이 CORS이다.

네 번째 기능은 CSRF(Cross Site Request Forgery), 사이트 간 요청 위조 보안 기능이다.
사용자가 웹사이트에 로그인하면 사용자 세션이 생성되는데, 이 사용자 세션은 브라우저의 쿠키를 사용해 식별된다. 만약 사용자가 이 웹사이트에서 로그아웃하지 않은 채 악성 웹사이트로 이동하면, 악성 웹사이트에서는 사용자의 인증 정보를 이전 브라우저에 있는 쿠키로 사용할 수 있다.
이러한 취약성을 CSRF, 사이트 간 요청 위조라고 한다. Spring Security를 추가하면 POST, PUT, 어떤 업데이트 요청에든 CSRF 보호가 자동으로 사용 설정된다.

다섯 번째 기능은 예외 처리이다.
인증과 권한 부여 관련해 예외가 발생할 때마다 세부적인 예외 정보를 그대로 사용자에게 보내는 것이 아니라 적절한 HTTP 응답으로 변환해야 한다. Spring Security는 ExceptionTranslationFilter를 통해 이러한 변환을 처리한다.

Spring Security는 액세스할 때마다 다양한 기능의 필터를 실행한다. 이 외에도 여러 기능이 존재한다. 중요한 것은 이러한 필터가 특정한 순서대로 실행된다는 점이다.