상세 컨텐츠

본문 제목

[Spring] Spring Security - 스프링 시큐리티

Backend

by choiDev 2024. 1. 11. 22:08

본문

Spring Security란?

시스템에 대한 인증(Authentication), 인가(Authorization)등의 기능을 가진 프레임 워크입니다.

 

 

Spring Security특징
강력한 인증 및 인가 지원 스프링 시큐리티는 다양한 인증 메커니즘을 지원하며, 세밀한 인가 기능을 제공합니다. 이는 폼 기반 인증, HTTP  Basic인증, OAuth, LDAP, JWT 등을 포함합니다.
세션관리 스프링 시큐리티는 세션 고정 보호, 세션 만료, 동시 세션 제어등 세션관리와 관련된 다양한 기능을 제공합니다.
CSRF(Cross-Site Request Forgery)보호 기본적으로 CSRF 보호가 활성화되어 있어, 웹 애플리케이션을 CSRF 공격으로부터 보호합니다.
Method Security @PreAuthorize @PostAuthorize @Secured  등의 어노테이션을 이용하여 메소드 레벨에서 세밀한 보안 설정이 가능합니다. 
표현언어 통합 스프링 시큐리티는 SpEL를 활용하여 보안 규칙을 표현하는데 사용 가능합니다.
LDAP 지원 LDAP 서버와의 통합을 지원하여 기업 환경에서의 사용자 인증 및 권한 관리를 용이하게 합니다.
REST API 보안  스프링 시큐리티는 Restful 서비스에 대한 인증 및 인가 자원을 포함하며, 상태를 유지하지 않는 서비스에 적합합니다.
디폴트 보안 구성 적절한 기본 설정을 제공하여, 보안 구성을 쉽게 시작할수있도록 합니다.

 

인증(Authentication), 인가(Authorization)

인증(Authentication)
- 해당 사용자가 본인이 맞는지를 확인하는 절차를 의미합니다. 사용자가 제공한 자격증명이 시스템에 등록된 정보와 일치하는지 확인합니다. 
- Spring Security에서는 AuthenticationManager + ProviderManager를 통해 인증과정을 관리합니다. 
- 사용자는 로그인폼, JWT토큰, LDAP등 다양한 방법으로 인증할 수 있습니다. Spring Security는 이러한 방법들을 지원하기 위해 다양한 AuthenticationProvider를 제공합니다.

인증의 방식은 다양하고 일부 정리해보자면 아래와 같고 본인 서비스와 보안에 맞는 것을 선택해야합니다.

Form-Based Authentication(폼기반 인증) 
- 가장 일반적인 인증 방식으로, 사용자는 웹 폼을 통해 자신의 자격을 제출합니다.
- 스프링 시큐리티는 UsernamePasswordAuthenticationFilter를 사용하여 이러한 요청을 처리합니다.

HTTP Basic Authentication(HTTP 기본인증)
- HTTP 헤더를 통해 사용자 이름과 비밀번호를 Base64 인코딩 형태로 전송합니다.
- 서버는 헤더를 디코딩하여 사용자를 인증합니다. 이 방식은 간단하지만 비밀번호가 암호화 되지 않기 때문에 보안에 취약합니다.

OAuth 2.0
- 외부 서비스(예: Google, FaceBook)를 통해 사용자를 인증하는 방식입니다.
- 사용자는 스프링 애플리케이션에 직접 자격 증명을 제공하는 대신, OAuth를 지원하는 제3자 서비스를 통해 인증을 수행합니다.

JWT(Json Web Token)
- 사용자 인증 후, 서버는 JWT를 생성하여 사용자에게 제공하며, 이후 사용자는 이 토큰을 포함시켜 서버에 전송합니다. 
- JWT는 자체적으로 사용자의 정보를 담고 있기 때문에 상태를 유지할 필요가 없어 RESTful 서비스에 적합합니다.

LDAP(Lightweight Directory Access Protocal)
- LDAP 서버를 사용하여 사용자를 인증하는 방식
- 주로 기업환경에서 네트워크내의 사용자 계정 정보를 관리하고 인증합니다. 

Remember-Me Authentication(자동 로그인)
- 사용자가 로그인할 때 자동 로그인 유지 옵션을 선택하면 스프링 시큐리티는 쿠키를 생성하여 사용자의 로그인 상태를 유지합니다.
- 이 쿠키는 사용자가 브라우저를 닫고 다시 열 때도 로그인 상태를 유지하는데 사용됩니다.

SAML(Security Assertion Markup Language)
- SAML은 단일로그인(Signle Sign-On, SSO) 시나리오에 많이 사용됩니다.
- 사용자는 하나의 인증으로 여러 애플리케이션에 접근할 수 있습니다.


인가(Authorization)
- 인증된 사용자가 특정 리소스에 접근하거나 작업을 수행할 권한을 가졌는지 확인하는 절차를 의미합니다.
- Spring Security에서는 주로 AccessDecisionManager를 사용해 인가를 결정합니다.
- 인가과정은 주로 GrantedAuthority 객체를 통해 관리됩니다. 사용자에게 부여된 권한들은 이 객체에 저장되며, Spring Security는 이 정보를 바탕으로 사용자의 권한을 확인합니다.


인가 방식 또한 다양하게 존재하는데 아래를 봐주시면 됩니다.

Role-Based Access Control(RBAC)
- 가장 일반적인 인가방식, 사용자에게 역할(예: 관리자, 사용자)을 할당하고, 각 역할에 따라 접근 가능한 리소스를 정의하는 방식

Attribute-Based Access Control(ABAC)
- 사용자, 리소스, 환경 등에 대한 속성을 기반으로 접근 결정을 내립니다. 
- 이방식은 유연하며 복잡한 접근 제어 정책을 구현할 수 있습니다.

Expression-Based Access Control(표현식 기반 접근 제어)
- 스프링 시큐리티는 SpEL(Spring Expression Language)를 사용하여 복잡한 접근 제어 규칙을 정의할 수 있습니다.
- 예를 들어, 특정 조건이 만족되었을때만 사용자가 특정 메소드를 호출하거나 리소스에 접근 할 수 있도록 설정할 수 있습니다.

URL Level Security
- 특정 URL 패턴에 대한 접근을 제어합니다.
- 예시 ("/admin/**")에 대해 특정 역할을 가진 사용자만 접근할 수 있도록 설정할 수 있습니다.

Method Level Security
- 서비스 레이어의 메소드 호출에 대한 보안을 적용합니다.
- @PreAuthrize @PostAuthorize @Secured 등의 어노테이션을 메소드에 적용하여 특정 권한을 가진 사용자만 해당 메소드를 호출할 수 있도록 할 수 있습니다. 

이 방식들은 단독사용 혹은 복합사용이 가능하니 적절한 인가 방식을 선택하는것이 보안 수준을 결정하는 중요한 요소입니다.

 

이제 인증과 인가방식을 알았으니 스프링 시큐리티의 인증과정 아키텍쳐가 어떻게 흐르는지 아래 흐름도를 보면서 정리해 보겠습니다.


Spring Security의 인증과정 아키텍쳐

1. HTTP 요청을 수신하고 AuthenticationFilter를 실행합니다.
AuthenticationFilter는 종류가 다양하기에 인증방식에 맞는 Filter를 사용해야하며 filter는 복합적으로 사용 가능합니다. 말그대로 filter 패턴은 filter를 쉽게 추가 하고 쉽게 제거가 가능하니 필요한 인증에 맞게 선정하시기 바랍니다..

UsernamePasswordAuthenticationFilter
- 폼 기반 로그인 처리를 담당합니다. 사용자가 로그인 폼을 통해 제출한 사용자 이름과 비밀번호를 처리합니다.

BasicAuthenticationFilter
- HTTP 기본 인증 요청을 처리합니다. 헤더에서 사용자 이름과 비밀번호를 추출하고 인증 수행합니다.

RememberMeAuthenticationFilter
- 기억하기 기능을 구현합니다.사용자가 이전에 로그인할 때 기억하기 옵션을 선택했다면 해당 필터가 사용자를 자동으로 인증합니다. 

AnonymousAuthenticationFilter
- 아직 인증되지 않은 사용자에게 익명 사용자의 정체성을 부여합니다. 이를 통해 인증되지 않은 사용자도 애플리케이션의 특정 부분에 접근할 수 있습니다. 

OncePerRequestFilter
- Http Request의 한번의 요청에 대해 한번만 실행하는 Filter입니다. 포워딩이 발생하면 필터체인이 다시 동작하는데 인증은 여러번 처리가 불필요하기에 한번만 처리를 할수있는 Filter이다.이외에도 많은 필터가 존재하니 별도로 필요한 필터는 찾아 보시는걸 추천합니다.

 

2.  인증토큰 생성

AuthenticationFilter가 요청을 interceptor 하고, 가로챈 정보를 통해 UsernamePasswordAuthenticationToken라는 인증용 객체를 생성합니다.

 

3. Filter를 통해 AuthenticationToken을 AuthenticationManager의 구현체인 ProviderManager에게 전달합니다.

4. ProviderManager는 AuthenticationProvider를 통해 인증 성공, 실패, 결정할 수 없음을 나타낼수 있습니다.

5. UserDetailsService의 요청 
DB에서 사용자 인증정보를 가져오는 UserDetailsService에 사용자 정보를 넘겨준다. 

6.넘겨받은 사용자정보를 통해 Spring Security에서 제공하는 UserDetails라는 클래스의 객체를 만든다. 

7. User 객체의 정보들을 UserDetails가 UserDetailsService(LoginService)로 전달 
AuthenticationProvider들은 UserDetails로 인증 절차를 진행합니다. 

8. 인증 객체 or AuthenticationException
인증이 완료되면 권한 등의 사용자 정보를 담은 Authentication 객체를 반환합니다.

9. 인증 완료
AuthenticationFilter로 Authentication 객체가 반환됩니다.

10. SecurityContext에 인증 객체를 설정
Authentication 객체를 Security Context에 저장한다. 

 

스프링 시큐리티의 인증 과정이 끝나게 되면 인가과정을 진행할수있다 하지만

스프링의 라이프사이클중에 Filter 부분에서만 인가를 하는것이아닌 Controller나 Service의 메소드와 같은곳에도 어노테이션을 통해 인가를 진행하여 특정 권한이 있는 유저만 사용하게도 할수 있다.

 

 

출처

https://blog.seongseob.dev/204

관련글 더보기