Hello World

1장 스프링 시큐리티란? 본문

Spring/3.x

1장 스프링 시큐리티란?

EnterKey 2016. 2. 24. 18:47
반응형

드디어 대망의 스프링 시큐리티입니다! 이것이 정녕 막판 보스는 아니지만 현재까지의 개발환경에서 스프링 시큐리티만 어느 정도 가닥이 잡힌다면 웹서비스 제작에 필요한 대부분의 요소는 자리를 잡게 되는 셈입니다. 게다가 스프링 시큐리티는 매우 지능적이며 대부분 간단한 선언만으로 작동하므로 대량의 코드를 손쉽게 절약해줍니다.


그러므로 스프링 시큐리티를 이용하는 것만으로도 고철자물쇠에서 최첨단 10 중 보안장치를 설치하는 것과 동일한 효과를 얻을 수 있겠다 말하겠습니다.
스프링 시큐리티는 강력하면서도 쉽습니다. 게다가 단 몇십줄의 코드만으로도 대형 웹서비스사와 비슷한 수준의 보안을 유지할 수 있다는 장점이 있습니다. 물론 진짜로 비슷한 수준을 유지하려면 적정 수준의 튜닝이 필요하겠지만 그 튜닝의 기반으로 삼기에 스프링 시큐리티는 정말 최상 중 최상의 선택입니다.

한가지 단점은 아직 한국에서 스프링 시큐리티에 대한 활용이 미비한 상태인데다 제대로된 포럼글이나 최신버전에 맞는 설명이 많지 않다는 것입니다. (덕분에 저도 문서를 작성하기 위해 필요한 정보를 찾느라 정말 애먹었습니다. 영어 모르는게 정말 서럽더군요.) 스프링 시큐리티가 ACEGI란 이름으로 시작해, 세상에 나온지 벌써 10년 가까이 됬음에도 아직까지 큰 관심이 없다는 것은 한국이 아직도 웹서비스의 발전이 미미하거나 보안에 대해 크게 간과하면서 많은 관심이 두고있지 않다는 사실일지도 모릅니다.

앞으로 이 포스트는 최소 3부 이상의 기나긴 마라톤 포스트가 될 예정이며 단순히 스프링 시큐리티를 활용하는데 그치지 않고 보안의 기본상식이나 개념에 대해 알아가는 시간이 되도록 할 예정입니다. 

그리고 이건 개인적인 이야기지만 시중에 나온 스프링 시큐리티3란 서적이 있긴 있는데 한글을 읽으면서도 외계어 읽는 듯한 기분을 느끼길 좋아하신다면 구매하셔도 상관은 없습니다… 그런 이유가 아니시라면 개인적으로 구매는 권장하지 않습니다. (현재까지 프로그래밍 서적에서 비추하는 책은 iBATIS 인 액션과 더불어 바로 이 책입니다. iBATIS 인 액션은 개발진이 직접 쓴 책이지만 솔직히 책이 필요없을 정도로 라이브러리가 너무 쉽습니다...;;)


보안이란?
위의 두 단어는 스프링 시큐리티 뿐만이 아니라 일반 보안에서도 핵심 축입니다. 개인적으로 너무나 중요하다 생각되어 하단 한글명에 욕심을 부려보았습니다. 게다가 많은 사람들이 Authentication과 Authorization의 이름이 비슷해 "명사형, 동사형 정도의 차이겠지"라며 착각하실 때가 종종 있는데 두 단어의 뜻은 전혀 다릅니다. 그러므로 글을 읽으시면서 비슷한 단어니까 비슷한 뜻이겠지… 라고 넘어가서는 절대 안됩니다.  한글 발음으로는 아우덴티케이션, 아우토리제이션입니다.

먼저 인증의 종류부터 알아봅시다. 인증에는 여러가지 종류가 있지만 보통 3가지로 분류하곤 합니다.

크리덴셜(Credential:자격) 기반 인증 : 우리가 웹에서 사용하는 대부분의인증 방식은 크리덴션 기반의 인증 방식입니다. 즉 권한을 부여받는데 1차례의 인증과정이 필요하며 대개 사용자명과 비밀번호를 입력받아 입력한 비밀번호가 저장된 비밀번호와 일치하는지 확인합니다. 일반적으로 스프링 시큐리티에서는 아이디를 프린시플(principle)비밀번호를 크리덴셜(credential)이라고 부르기도 합니다.
이중 인증(Two-factor authentication) : 한번에 2가지 방식으로 인증을 받는 것을 말합니다. 예를 들어 금융, 은행 웹어플리케이션을 이용해 온라인 거래를 하실 때에는 로그인과 보안 인증서, 2가지 방법으로 인증을 받곤 합니다. 별 것 아닌 것 같지만 Authentication이 하나 추가됨으로서 프로그래밍 적으로 변화해야 할 부분은 상당히 광범위해집니다.
물리적인 인증 : 이 부분은 웹의 영역을 벗어난 것이지만 가장 효과적인 보안 수단 중에 하나입니다. 예를 들어 컴퓨터를 킬 때 지문을 인식받는다거나 키를 삽입해야 하는 것들 말입니다. 

앞으로 우리가 스프링 시큐리티를 이용해 구현해나갈 인증(Authentication)은 눈치채셨겠지만 바로 크리덴셜(Credential) 인증입니다. 그리고 한가지 말씀드리고 싶은 것은 보안용어에 대해 잘 모르신다면 여기서 나오는 영어 단어들을 유심히 살펴보고 한번씩 써보는 것이 좋습니다.

왜냐하면 이런 용어들이 앞으로 스프링 시큐리티의 클래스, 또는 메서드 명으로 나오게 되며 보안용어에 익숙치 않은 독자는 앞으로 문서를 읽어 나가면서 굉장히 혼란스러울 수도 있기 때문입니다. 그러므로 이런 문제를 미리 방지하기 위해서라도 사전적 의미만으로 표현할 수 없는 보안용어의 참 의미를 미리 숙지할 수 있도록 주의깊게 읽으셔야 합니다.

이제 인증(Authentication)의 종류에 대해 어느 정도 이해가 되셨면 다음은 권한부여(Authorization) 차례입니다. 권한부여에는 크게 2가지로 나뉠 수 있습니다.

부여된 권한(Granted Autority) : 적절한 절차로 사용자가 인증되었다면 권한을 부여(Granted Authority)해야 할 것입니다. 회원가입 등을 통해 반영구적인 권한이 부여됬다면 우리는 이 회원에게 부여된 권한을 어딘가에 저장해야 하구요. 만약 해당 사용자가 로그인을 했는데 메인 페이지로 넘어갈 수 없다면 권한부여에 문제가 있다는 것이겠죠.
리소스의 권한(Intercept) : 사용자의 권한만 있다고 보안이 제대로 동작할리는 없습니다. 보안이란 본래 권한이 없는 자들이 원천적으로 리소스에 접근할 수 없도록 막아내는 것이기 때문입니다. 그런 의미에서 적절한 권한을 가진자만 해당 자원에 접근할 수 있도록 자원의 외부요청을 원천적으로 가로채는 것(Intercept)이 웹보안, 그 중 권한부여(Authorization)의 핵심 원칙이라 할 수 있겠습니다.

위의 보안 용어들은 중요한 개념이라고도 할 수 있지만 한편으로는 골치아픈 해결과제라고도 할 수 있습니다. 즉 우리가 위와 같은 주요 개념들에 입각해 구현해야 할 보안을 생각해본다면 일단 우선적으로 "어떤 방식으로 권한을 부여할까?""해당 리소스에 어떻게 권한수준을 부여하지?""인증받은 사람은 어떻게 인증받았다는 정보를 지속적으로 유지할 수 있을까?"와 같은 골치아픈 과제들이 산더미같이 존재할 수 있을 것입니다. 게다가 문제들을 해결하는 것도 힘든 일이지만 일을 더욱 더욱 어렵게 만드는 것은 보안이 아무리 잘해도 티 안나고 한번만 실수해도 독박은 다 뒤집어쓰는 전업주부 방식의 프로그래밍 분야이라는 것입니다.

그러므로 위와 같은 문제들의 올바른 해결을 위해서라도 스프링 시큐리티의 손을 한번 더 들어주고 싶어집니다. 스프링 시큐리티는쉽고 편리하다는 장점도 있지만 이런 보안 개념이 없는 자가 보안이 필요한 쇼핑몰이나 주요 웹사이트를 설계했다고 가정했을 때 발생할 막대한 피해들을 방어할 수 있는 최선의 선택입니다. 스프링 시큐리티는 이런 과제들을 거의 10년 가까이 연구하며 발전해온 뛰어난 보안 프레임워크라는 점을 볼 때 우리에게 스프링 시큐리티는 선택이 아니라 필수라고도 할 수 있습니다.

이제 보안의 핵심용어와 스프링 시큐리티의 중요성에 대해 어느 정도 설명했으니 스프링 시큐리티에 대해 좀 더 깊이 들어가 발생하는 문제에 어떤 해결방식을 선택했는지 차근차근 집어나가보려고 합니다.

리소스의 권한(Intercept)

리소스의 권한이 영어로 Intercept가 아니라는 것쯤은 저도 스타크래프트를 조금 해봤으므로 알고 있습니다. 그럼에도 Intercept라는 말을 리소스 권한 옆에 당당히 붙여놓는 것은 보안에서 리소스에 접근권한을 설정하는 것이 바로 Intercept 방식으로 작동하고 있기 때문입니다. 아무리 서버 성능이 좋고 직원이 많더라도 우리가 가지고 있는 모든 리소스에 일일이 권한을 설정할 수는 없는 노릇입니다. 대신에 우리가 @MVC에서 보았듯 DispatcherServlet처럼 멋지게 클라이언트의 요청을 가로챌 수만 있다면 간단히 문제를 해결할 수 있을 것입니다.

개인적으로 @MVC의 개발에 간접적으로나마 스프링 시큐리티가 많은 공헌을 하지 않았을까 생각하는데 그 이유는 스프링 시큐리티가 이미 ACEGI 때부터 Filter를 이용해 클라이언트의 요청을 가로채는 하는 방식을 굉장히 오래 전부터 개발해놨었기 때문입니다. (Spring Security는 스프링 커뮤니티에 합류하기 전까지 Acegi라는 이름의 프레임워크였습니다. 이름이 Acegi인 이유는 13579순서대로 알파벳을 정렬했다고 하는군요.) 그렇기 때문에 스프링 시큐리티는 @MVC의 DispatcherServlet이나 AOP를 이용해 프록시를 생성하지 않고 아주 오래 전부터 사용해온 고유의 DelegatingFilterProxy 클래스를 사용합니다. 물론 DelegatingFilterProxy를 이용하면서도 AOP 포인트컷의 활용 또한 가능합니다.

먼저 기존의 제작된 프로젝트에 다음과 같이 web.xml에 DelegatingFilterProxy를 등록해 봅시다.
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/-</url-pattern>
</filter-mapping>

여기서 주의할 점은 <filter-name>의 값이 반드시 springSecurityFilterChain이어야 한다는 점입니다. 왜 꼭 이름을 springSecurityFilterChain으로 지어야 하냐면 DelegatingFilterProxy 클래스는 setTargetBeanName(String)이라는 메서드를 갖고 있는데 이 메서드는 실제 요청을 처리할 필터를 주입받습니다. 만약 이 메서드를 통해 구현할 필터빈을 주입받지 못한다면 DelegatingFilterProxy 클래스는 기본값으로 <filter-name>의 값과 동일한 빈이 스프링 컨텍스트에 존재하는지를 검색하게 됩니다.

그러나 곧 알게 되겠지만 DelegatingFilterProxy 클래스가 springSecurityFilterChain이란 빈이 필요하다고 직접 빈을 만들어줄 필요는 없습니다. 왜냐하면 springSecurityFilterChain은 스프링 시큐리티의 inner bean이기 때문에 자동으로 생성되기 때문이죠.


이런 관점에서 본다면 DelegatingFilterProxy는 굳이 스프링 시큐리티 에서만 사용할 게 아니라 다른 목적의 필터 체인으로도 충분히 사용될 수 있는 확장성이 존재합니다. 아마 스프링 제작진들도 이 클래스가 스프링 시큐리티에서 탄생했지만 역할의 중요성을 인식해 시큐리티 내부 패키지에 위치시키지 않고 org.springframework.web.filter에 등록시킨 것 같습니다.

아마 이쯤되면 어떤 예리한 독자 분이 "DispatcherServlet이 이미 모든 요청을 가로채는데 또 DelegatingFilterChain이 가로채면 우선순위는 어떻게 결정되나요?" 라는 질문을 던지실 수도 있겠군요. 정답만 이야기하자면 필터가 우선순위가 됩니다. web.xml을 보면 알다시피 DispatcherServlet은 서블릿으로 등록되있고 DelegatingFilterChain은 필터로 등록되어 있습니다. 만약 이런 상황에 서로 겹치는 URL이 요청으로 들어온다면 필터는 프록시 패턴처럼 서블릿을 샌드위치 해버립니다. 이런 점에서 본다면 우리는 왜 DelegatingFilterChain이 필터로 만들어졌으며 DispatcherServlet이 왜 서블릿으로 만들어졌는지 이해할 수도 있겠죠.

이제 필터를 이용해 모든 URL이 DelegatingFilterProxy를 통과하도록 설정했다면 컨텍스트를 설정할 차례입니다. 보안에 대해서 따로 관리해줄 컨텍스트 파일을 만드는 것이 좋으므로 security-context.xml이란 파일을 새로 만들도록 합시다. 그리고 완성된 빈은 web.xml에 등록하는 것도 잊지 말구요. 여기까지 완료하시면 스프링 시큐리티를 사용하기 위한 기본 세팅은 마무리 됩니다.

어떠셨나요? 글을 읽으시면서 어느 정도 보안에 대해 감이 오시나요? 만약 아무리 읽어도 감이 오지 않는다면 스스로 의문을 만들고 그 답을 찾아보도록 노력해보세요. 개인적으로 스프링 시큐리티 API문서를 찾아보시길 권장합니다 ^^; 그럼 글이 길어지는 관계로 이번 장에선 보안의 기본원리와 스프링 시큐리티의 기본 세팅까지 다루고 다음 장부터 본격적으로 security-context.xml을 이용한 보안설정을 다루도록 하겠습니다. 여기까지 읽어주셔서 감사하구요. 좋은 하루 되세요 :D


출처: http://springmvc.egloos.com/504862

반응형
Comments