minwoorich / 2024-spring-jpa-study

4 stars 5 forks source link

스프링 시큐리티가 뭐야 도대체?!?!?!🤷‍♂️🤷‍♀️ #53

Open minwoorich opened 4 months ago

minwoorich commented 4 months ago

➡️➡️ 블로그 바로가기

1. Spring Security 소개

✏️ 스프링 시큐리티 란?

Spring Security is a framework that provides authentication, authorization, and protection against common attacks. With first class support for securing both imperative and reactive applications, it is the de-facto standard for securing Spring-based applications.

스프링 시큐리티는 인증, 인가, 그리고 일반적인 보안 공격 유형으로부터 방어 할 수 있는 기능을 제공한다. 명령형(서블릿 기반), 리액티브(비동기) 어플리케이션 모두에게 보안 기능을 지원해주며, 이는 사실상 스프링 기반 어플리케이션의 보안 표준이다.

SpringSecurity 공식 가이드

쇼핑몰, 회사 홈페이지, 어플, 플랫폼 사이트 등 모든 웹 개발에서 빠질 수 없으며 가장 중요한 것중 하나가 바로 "보안" 이다. 이 보안을 위해서 많은 개발자들은 인증, 인가, 세션 관리 등에 많은 시간을 할애하게 되는데 이게 여간 보통일이 아니며 굉장히 머리를 많이 쓰게 된다. 특히 보안 쪽은 법과도 밀접한 녀석인지라 자칫 해커들에 의해 사이트 회원 정보가 유출이라도 된다면 털린 회사는 막대한 손해 배상을 사용자들에게 해야 할 수도 있다.

그래서 이를 가엽게 여긴 스프링 진영에서는 개발자들의 여러 보안적 요구사항들을 모아 모아 보안 프레임워크를 개발하였는데 그것이 바로 바로 "Spring Security" 인 것이다. 이 덕분에 스프링 기반 어플리케이션 개발자들은 이전에 비해 훨씬 빠르고 효율적이며 또 굉장히 안전한 어플리케이션을 개발 할 수 있게 되었다. 노드는!!

🤷‍♂️ 스프링 시큐리티 사용하면 뭐가 좋은데?

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.

Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements

SpringSecurity 공식 가이드

위에 설명글과 중복 되는 내용이 많으니 강조된 부분만 살펴 보자면 계속해서 "커스텀 하기 편하다~" 라는 식으로 어필을 하고 있다.

즉, 스프링 시큐리티를 사용하면 강력한 보안 기술을 지원받을 수 있는건 물론이며 상황에 맞춰 자기 입맛대로 커스터마이징이 가능하단것이다. 앞으로 쭈욱 스프링 시큐리티 구조를 학습하면서 이런것들을 계속 살펴볼 터이지만 그래도 한 번 맛보기로 살짝 코드를 살펴보자.

AuthenticationProvider 인터페이스

이것은 스프링 시큐리티에서 제공하는 AuthenticationProvider 라는 인터페이스이며 코드로 확인 할 수 있다시피 인증 처리 역할을 맡고 있다.

스프링에서는 해당 인터페이스에 대해 기본적인 구현체들을 제공을 해주기 때문에 그냥 그걸 그대로 사용해도 큰 문제는 없다. 하지만, 좀 더 다양하고 복잡한 인증 처리를 추가하고 싶거나 혹은 아이디/비밀번호 방식 말고 다른 방식(지문 인증, 홍채 인식, JWT 토큰 방식 등) 을 사용하는 경우가 생길 수 있는데, 이럴 땐 그에 맞게 커스터마이징 된 구현체를 개발자가 직접 해당 인터페이스를 상속 받아서 구현을 하면된다.

커스터마이징 된 AuthenticationProvider

😱 하지만 스프링 시큐리티 없이 이런 객체들을 구현해야한다면??

스프링에서 추구하는 확장성과 고도의 객체지향적인 설계를 고려하면서 개발한다는게 프레임워크의 도움 없이는 굉장히 어려운 일일 것이다. 하지만 스프링 시큐리티를 사용한다면 어느정도 방향성과 체계를 잡혀져있기 때문에 개발 생산성이 훨씬 더 증가할 수 있다.

즉, 정리하자면

❤️ 각종 보안에 필요한 여러 클래스 파일들이 미리 사용할 수 있도록 정의 되어있다 💚 커스터마이징을 지원함으로써 환경별로 유연한 설계 및 개발이 가능하다 💙 프레임워크의 도움을 받아 보다 쉽고 효율적 으로 확장성 있는 어플리케이션 개발 이 가능하다

과 같은 장점이 있다고 볼 수 있다.

2. 스프링 시큐리티가 제공하는 기능

앞에서 스프링 시큐리티가 제공하는 대표적인 기능들로 인증, 인가, 보안 공격 방어 가 있다고 살짝 언급하였는데 이것들에 대해 좀 더 자세히 알아보자.

🔒 Authentication (인증)

Spring Security provides comprehensive support for authentication. Authentication is how we verify the identity of who is trying to access a particular resource. A common way to authenticate users is by requiring the user to enter a username and password. Once authentication is performed we know the identity and can perform authorization.

Spring Security provides built-in support for authenticating users. This section is dedicated to generic authentication support that applies in both Servlet and WebFlux environments. Refer to the sections on authentication for Servlet and WebFlux for details on what is supported for each stack.

... 인증 이란 특정 자원에 접근하려고하는 이의 신원을 입증하는 것을 말한다.
...

SpringSecurity 공식 가이드

서버(Server) 는 그 이름에서부터 알 수 있다시피 근본적으로 사용자에게 무언가를 "서빙" 해주는 녀석이다. 즉, 사용자들은 서버가 가지고 있는 자원에 대해 요청을 보내고 서버는 그 자원을 전달해준다. 하지만 특정 경우에는 이 자원들이 만인에게 공유되어선 안 되는 경우도 있다.

예를 들어, 집 주소, 주민등록번호 와 같이 정말 민감한 개인 신상 정보가 있을 수도 있고 뿐만 아니라 내가 구매한 상품 목록 , 내가 묵었던 숙박 업체 명과 날짜 시간 과 같이 굳~이 남들에게 알려줄 필요가 없는 정보들도 포함이 될 수 있다.

이런 데이터들에 대해 나 혹은 내가 지정한 몇몇 소수에게만 접근을 허용하고 싶은 경우에 바로 이 "인증" 이라는 기술이 필요로 해지는 것이다.

스프링 시큐리티가 제공하는 Authentication 방식

스프링 시큐리티는 굉장히 다양한 인증 방식들을 제공해주는데 대표적으로 Username and PasswordOAuth 2.0 Login 가 있다.

뿐만 아니라 위 와 같이 각종 다양한 인증 방식들이 있으며 물론 개발자 입맛에 맞춰 이것들을 커스터 마이징 하는것도 가능하다. SpringSecurity 공식 가이드

🛂 Authorization (인가)

Spring Security provides comprehensive support for authorization. Authorization is determining who is allowed to access a particular resource. Spring Security provides defense in depth by allowing for request based authorization and method based authorization.

... 인가는 누가 특정 리소스에 접근 할 수 있는지 결정하는 것을 의미한다. ...

SpringSecurity 공식 가이드

언뜻 보면 인증과 인가 모두 설명이 똑같아보인다. 실제로 비슷한 개념이긴 하나 그럴지라도 엄연히 구분되어지는 다른 개념이다. 예시를 들어 설명해보자.

예를 들어, 갓 입대한 이등병 A와 중대장 B가 있다고 하자.

A, B 모두 군인 신분이기에 위병소에서 신원 확인(인증) 이 된다면 군 부대 출입이 허용된다. 하지만 군인이라고 해서 다 같은 군인은 아니다. 직급이 높은 B는 군사 기밀 문서를 읽을 수 있는 권한(인가) 을 가지고 있지만 A는 그렇지 못 한다.

즉, 인증 은 아까 설명대로 나의 신원을 입증 하는 것임이고 인가 는 각 개인 혹은 그룹별로 가질 수 있는 권한을 부여 하는 것이다.

스프링 시큐리티가 권한을 부여 하는 방식

스프링시큐리티에서는 크게 두가지 방식으로 사용자에게 권한을 부여할 수 있다.

하나는 요청 기반 , 다른 하나는 메서드 기반 이다.

지금은 간략한 소개 타임이니깐 둘 의 자세한 내용은 학습을 통해 차차 알아가보는 것으로 하자.

🛡️ Protection Against Exploits (취약점 공격 방어)

사실 많은 개발자들이 SW를 개발 할 때 보안 적인 측면에는 살짝 신경을 덜 쓰는 경향이 있다. 개발자들이 게을러서라기 보다는 당장 비즈니스로직을 짜는 것만해도 머리가 아픈데 보안까지 신경을 쓸 겨를이 없다. 그리고 애초에 보안이라는 개념 자체가 굉장히 역사가 깊으며 유구한 전통을 가지고 있는 학문인지라 파도파도 끝이 없다. 그래서 학습 곡선도 상당한 편이다.

보안 취약점

그래서 많은 어플리케이션들이 중간 중간 보안 측면에서 허점들이 많이 생길 수 있는데 이를 취약점 이라고 부른다. 사실 보안에 정말 많은 신경을 썼다할 지라도 생각지도 못 한곳에서 취약점이 생길 수 있는데 이런 빈틈들을 약삭 빠른 해커들은 놓치지않고 공략을 하는것이다. 이러한 공격 행위를 "취약점 공격" 이라 한다. 위키 백과

이 취약점이라는 것은 주로 근본적인 설계 결함에 의해 발생 한다.

CSRF(Cross-Site Request Forgery)

대표적인 취약점 공격으로 CSRF(Cross-Site Request Forgery) 공격이 있는데 이는 서버의 세션관리의 취약점 을 파고들어 공격하는 방식이다.

이 공격을 간단히 설명하자면 악의적인 해커가 이미 인증에 성공한 클라이언트의 세션 쿠키값을 가로챈 다음, 마치 인증된 회원인 척 요청을 보내는 것이다. 그러면 서버는 정상적인 사용자가 보낸 요청인 줄 알고 요청 받는대로 리소스를 넘겨주는것이다. 당연히 여기에는 각종 개인정보가 포함될 수 있으며 좀 더 응용하면 해커의 계좌로 돈을 입금 하도록 하는 요청도 보낼 수 있을 것이다.

이러한 공격이 가능한 이유는 서버는 기본적으로 인증된 사용자의 요청을 구분하지 못하기 때문 이다. 서버-클라이언트 통신은 기본적으로 stateless 하기 때문에 서버가 모든 사용자들의 정보를 저장하고 있지 않다. 하지만 그렇다고 진짜 아무것도 저장을 안 하는건 아니고 "세션" 이라는 저장소에다가 사용자를 구분할 수 있도록 사용자가 최초 로그인시 사용자와 "세션아이디" 라는 키값을 서로 매핑 시켜서 저장 해놓는다. 그리고 그 키(세션아이디) 를 클라이언트에게 나눠준다.

그러면 클라이언트는 그 입장권을 자기 컴퓨터에 고이 저장해두고 있다가 다시 서버에 요청을 보낼때 브라우저가 자동으로 그 입장권을 서버에게 보여준다. 즉, 세션아이디는 일종의 입장권 인 셈이다.

여기서 문제가 발생하는데 이 입장권을 만약 누군가가 훔쳐간다면?

즉, 누구든지 이 입장권만 가지고 있다면 서버는 아묻따 들여보내주는것이다. 그게 설령 해커일지라도 말이다. 이렇듯 서버는 일단 인증에 성공만 하면 무엇이든 들어주는 바보같은 녀석이기 때문에 이러한 취약점을 해커들은 잘 파고들어 공격을 하는 것이다.

아무리 우리집 현관문에 자물쇠를 100개를 걸어두고, 굴뚝을 막고, 창문을 철창으로 막아놔도 도둑이 우리집 키만 가지고 있다면 완전 말짱꽝이 되는 셈이다. 이런 취약점 공격이 웹 세상에선 굉장히 다양하며 실제로 이러한 공격들이 비일비재하다.

웹 에서의 취약점 공격은 CSRF 말고도

등등 많이 존재한다.

사실 이런 공격 유형들은 이미 세상에 널리 알려져있기 때문에 이미 방어에 대한 수 많은 방법론과 공격 무효화 기법들이 존재한다. 하지만 그렇다고해서 이런 공격들이 사라진것은 절대 아니다. 앞서 말했듯이 사람들은 보안에 대해 잘 신경을 쓰지 않기 때문에 저런 공격들이 있다는 것조차 잘 인지하지 못 한다. 설령 인지는 했을지라도 그것을 방어하는 코드를 짜는것은 꽤나 학습이 필요하기에 어설프고 허술하게 짜는 경우가 생긴다.

그래서 스프링 시큐리티는 위와 같이 유명한 취약점 공격들에 대해 방어를 하는 기술들을 적극 지원해준다.

🤷‍♂️ 어떻게 지원해주냐고?

이것들 또한 차차 학습을 통해 알아가볼 것이다.

🤝 Integrations (기술 통합)

이건 설명할게 별로 없으니 짧게 설명하겠다. (별게 아니란 뜻이 아니라 개념적으로 설명할게 별로 없다는 뜻이다. 내부적으론 뭐가 굉장히 많다.)

스프링 시큐리티는 다양한 외부 서비스 혹은 스프링진영의 다른 프레임워크와 연계하여 사용 할 수 있다. 대표적으로 서블릿 API와 통합되어 보안 설정 관리를 중앙 집중화 시킬 수 있으며 확장성, 유연성 또한 보장해준다.

자세한 내용은 SpringSecurity 공식 가이드 를 살펴보자.

3. 마무리

스프링 시큐리티를 공부하다보면 굉장히 어렵고 버겁게 느껴질 때가 많을 것이다.

왜냐하면 다른 스프링 MVC 프레임워크나 혹은 JPA 와 같은 경우 내부 동작 원리와 구조에 대해 정말 세세하게 까지 알 필요는 없다. 우선 사용법만 익히고 바로 실무에 적용해도 어느정도 먹힌다. (상대적으로 그렇다는 말!!)

하지만 스프링 시큐리티의 경우 그 내부의 동작 원리와 구조 까지 정말 꽤나 자세히 알고 있어야지만 비로소 사용할 수 있게 된다. 물론 사용법만 익히고 바로 실무에 도입을 "할 순 있다". 하지만 그럴 경우 문제가 터졌을 때 정말 큰 일이 발생한다.

문제가 터졌을 경우 사용자의 입력 값이 어느 필터를 통해 처리 되고, 어떤 객체에 무슨 값이 초기화 되고, 어느 토큰이 저장되어지고 나가고 이런 일련의 과정들을 하나하나 디버깅을 해야하는데 동작원리나 구조를 이해 못하고 있다면 그냥 생각없이 step into 버튼만 누르고 있을 가능성이 농후하며 아니 애초에 어디에 브레이크 포인트를 걸어야 할 지 조차 감이 안 올 것이다. 그러다보니 결국 원인을 해결하지 못하고 도입 되었던 시큐리티 코드를 다 걷어내는 경우가 비일비재하다.

그래서 스프링 시큐리티를 공부 할 때는 반드시 내부구조를 최대한 머릿속에 박 힐 때까지 학습을 하고 이를 위해선 스프링 시큐리티의 객체들이 초기화 하는 과정을 디버깅을 찍으면서 확인하는 이런 반복 숙달 훈련 하는 것을 추천드린다.

📚 참고 자료 https://docs.spring.io/spring-security/reference/index.html

https://www.elancer.co.kr/blog/view?seq=235

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-%EC%99%84%EC%A0%84%EC%A0%95%EB%B3%B5/dashboard