1. 스프링 시큐리티 활성화
스프링 시큐리티가 제공해주는 기본적인 보안 기능은 다음과 같다
- 애플리케이션 사용자 인증
- 별도의 로그인 페이지가 없을 때 사용할 수 있는 기본적인 로그인 페이지
- 폼 기반 로그인에 사용할 수 있는 기본 계정
- 사용자 인증 성공 후 세션 ID를 교체해서 세션 고정 공격 방지
- HTTP응답 코드에 랜덤 문자열 토큰을 포함해서 사이트 간 요청 위조 공격 방지
- 공통적으로 자주 발생하는 보안 공격을 방어할 수 있는 여러 가지 HTTP 응담 헤더 제공
그 외에도 보안을 높일 수 있는 여러 가지 HTTP응답 헤더 관련 내용을 스프링 시큐리티 공식 문서(https://mng.bz/W74g)에서 확인할 수 있다.
스프링 시큐리티를 사용하기 위해서는 스프링 시큐리티 스타터 의존 관계를 넣어줘야 한다.

이렇게 의존성을 추가하고 아무런 코드를 넣지 않은 채 실행하면

자동으로 localhost:8080/login으로 넘어가는 것을 확인할 수 있다.
여기서 로그인을 해야 원래 나오는 애플리케이션을 실행시킬 수 있다.
맨 처음 로그인은
- ID: user
- password는

로그에 나오는 값으로 로그인이 가능하다.
이렇게 넘어가는 이유는 스프링 시큐리티가 적용된 애플리케이션은 HTTP요청/응답이 있을 때 서블릿으로 가기 전에 필터가 중간에 요청-응답을 가로채기 때문이다.
Filter 인터페이스는 초기화 > 서비스 > 소멸 의 라이프 사이클을 돌며 실질적인 로직은 서비스 부분에서 요청과 응답이 출입한다.
- init(): 서블릿 컨테이너가 필터를 등록하는 초기화 과정에서 호출
- doFilter(): 필터의 실질적인 작업을 수행, 요청, 응답, FilterChain객체에 접근 가능
- destroy(): 서블릿 컨테이너가 필터를 제거할 때 호출
FilterChain은 1개 이상의 필터가 존재할 때 그 필터를 연쇄적으로 거쳐서 흘러가게 만드는 역할을 한다.
2. 스프링 시큐리티 아키텍처
스프링 시큐리티의 필터인 DelegatingFilterProxy, FilterChainProxy, SecurityFilterChain 에 대해 알아본다
- DelegatingFilterProxy: 서블릿 컨테이너에서 동작하는 일반적인 필터처럼 동작하지만, 실제 필터의 로직 처리는 Spring 컨텍스트에 정의된 delegate로 설정된 스프링 빈에 위임해서 처리한다.
- FilterChainProxy: DelegatingFilterProxy의 대리인 역할을 하는 Filter 인터페이스 구현체다.
- SecurityFilterChain: FilterChainProxy구현체에 1개 이상 들어있는 FilterChain이다
DelegatingFilterProxy가 필터로 가로챈 요청을 FilterChainProxy가 위임받고 FilterChainProxy가 가지고 있는 SecurityFilterChain에 요청을 보내 필터를 통과하게 만든다.
SecurityFilterChain에는 matches()와 getFilters() 메서드가 있다.
- matches(): SecurityFilterChain구현체가 요청을 처리하기 적합한지 판별
- getFilters(): matches()메서드가 true를 반환하면 호출되며 실질적으로 doFilter()역할을 한다.
3. 스프링 시큐리티 자동구성
스프링 시큐리티 자동 구성을 확인하기 전에 기존의 스프링 사용자 인증 과정을 설명한다.
3.1.1. SecurityContextHolder
- 현재 인증된 사용자의 SecurityContext를 저장하고 관리한다.
- SecurityContext는 Authentication 객체를 포함하며, 인증된 사용자의 세부 정보와 권한 정보를 보유하고 있다
- 기본적으로 스레드 로컬(ThreadLocal)을 사용하여 요청이 끝날 때까지 인증 정보를 유지합니다.
3.1.2. AuthenticationFilters
- 사용자 정보를 인증하는데 사용되는 인증 필터로 스프링 시큐리티는 여러 인증필터를 제공한다.
- 사용자 자격 증명(예: 사용자 이름과 비밀번호)을 추출하고 인증 매니저(AuthenticationManager)에 전달합니다.
- 핵심 인증필터:
- UsernamePasswordAuthenticationFilter: 기본 로그인 처리 필터로, 사용자 이름과 비밀번호를 처리한다.
- BearerTokenAuthenticationFilter: JWT와 같은 토큰 기반 인증을 처리한다.
3.1.3. ExceptionTranslationFilter
- 인증 또는 권한 부여 과정에서 발생하는 예외를 처리합니다.
- 인증 실패로 AuthenticationException이 발생하면 AuthenticationEntryPoint로 리다이렉트해서 다시 인증 과정이 진행되게 한다.
3.1.4. UserDetailsService
- 사용자 정보를 로드하는 데 사용된다.
- AuthenticationManager가 사용자 이름으로 사용자 세부 정보를 가져올 때 호출된다.
- 커스터마이징이 가능하다.
3.1.5. AuthenticationProvider
- 사용자의 자격 증명을 검증하고 인증 여부를 결정한다.
- 인증에 실패하면 AuthenticationException을 반환한다.
3.1.6 인증 과정 요약
- 요청 처리:
- 클라이언트가 자격 증명을 포함하여 인증 요청을 보낸다
- AuthenticationFilter:
- 요청을 가로채고 사용자 이름과 비밀번호를 추출한다.
- AuthenticationManager에 인증을 위임한다.
- AuthenticationManager:
- 하나 이상의 AuthenticationProvider를 사용하여 자격 증명을 검증한다.
- 인증이 성공하면 Authentication 객체를 반환한다.
- SecurityContextHolder:
- 반환된 Authentication 객체를 SecurityContext에 저장하여 요청 전체에서 인증 정보를 유지한다.
- 응답 처리:
- 인증이 성공하면 요청을 처리하고 성공 응답을 반환한다.
- 인증 실패 시 ExceptionTranslationFilter가 예외를 처리한다.
그럼 이제 스프링 시큐리티 자동 구성을 설명한다.
스프링 부트는 SecurityAutoConfiguration, UserDetailsServiceAutoConfiguration, SecurityFilterAutoConfiguration 이 세개의 설정 클래스로 자동구성을 수행한다.
3.2.1. SecurityAutoConfiguration
SpringBootWebSecurityConfiguration, WebSecurityEnablerConfiguration, SecurityDataConfiguration 이렇게 세개의 클래스를 사용해서 자동 구성을 수행한다.
세 개의 클래스의 역할을 간단하게 말한다면
- SpringBootWebSecurityConfiguration: 웹 보안의 기본 설정을 제공.
- WebSecurityEnablerConfiguration: Spring Security 웹 보안을 활성화.
- SecurityDataConfiguration: 데이터베이스 기반 사용자 인증 및 권한 부여 지원.
로 볼 수 있다.
SecurityAutoConfiguration 클래스에 @Import로 세 개의 클래스를 지정해서 생성하는 빈을 사용할 수 있는데 중요한 부분은 WebSecurityEnablerConfiguration 클래스의 @EnableWebSecurity애너테이션이다.
@EnableWebSecurity애너테이션은 WebSecurityConfiguration, HttpSecurityConfiguration클래스를 Import하고 @EnableGlobalAuthentication 애너테이션을 포함하고 있어 중추적 역할을 한다.
- 모든 SecurityFilterChain에 전역적으로 적용되는 AuthenticationManager를 AuthenticationManagerBuilder 인스턴스를 사용해서 설정할 수 있게 해준다.
- 개발자가 작성한 커스텀 설정 없이 자동 구성될 때도 @EnableWebSecurity애너테이션 효과가 발생하는 것을 보장한다.
세 클래스의 주요 관계로는
SpringBootWebSecurityConfiguration:
- 기본 웹 보안을 설정하는 역할을 한다.
- 커스터마이징되지 않은 경우 기본 보안 정책을 제공한다.
WebSecurityEnablerConfiguration:
- Spring Security의 웹 보안 활성화를 보장한다.
- @EnableWebSecurity와 동일한 역할을 수행한다.
SecurityDataConfiguration:
- 스프링 시큐리티와 스프링 데이터를 연동하는 데 사용된다.
3.2.2. UserDetailsServiceAutoConfiguration
UserDetailsServiceAutoConfiguration클래스는 애플리케이션에 UserDetailsService구현체가 빈으로 등록돼 있지 않으면 InMemoryUserDetailsManager를 빈으로 등록해줘서 사용자 이름이 user, 비밀번호가 랜덤UUId인 기본 계정을 생성해준다.
개발자가 직접 UserDetailsService의 구현체를 만들어 빈으로 등록하면 UserDetailsService 구현체가 활성화된다.
3.2.2. SecurityFilterAutoConfiguration
SecurityFilterAutoConfiguration 클래스는 DelegatingFilterProxyRegistrationBean을 생성해서 DelegatingFilterProxy 필터를 생성하고 서블릿 컨테이너에 등록하는 역할을 한다.
3. 스프링 시큐리티 적용
3.1 인메모리 인증 적용
SecurityConfiguration 소스안에 InMemoryUserDetailsManager구현체를 직접 만들어서 고정된 비밀번호를 가진 계정을 만드는 방식이다.

user계정과 admin계정을 만들고 계정의 권한또한 구분지었다.

구분된 권한은 hasRole메서드를 통해 사용된다. 만일 ADMIN역할이 없는 계정이 접근하면 예외처리핸들러를 통해 주입받은 customAccessDeniedHandler를 통해 처리된다.
3.2 JDBC 인증 적용
소스코드에 계정 정보를 넣는 방식은 소스를 볼 수 있으면 누구든지 계정 접근이 가능하기 때문에 안전하지 않다.
안전한 프로젝트를 위해서는 외부 저장소로 계정 정보를 빼야 하는데 가장 직관적인 DB를 이용하는 방식이다.

먼저 유저정보와 권한을 저장하는 테이블을 schema.sql에 넣는다.

그 후 data.sql에 유저정보와 권한을 저장한다.
SecurityConfiguration 소스안에 계정 정보를 직접 넣는 대신에

DataSource를 주입받아서 처리한다.

주입받은 DataSource를 사용해서 JDBC인증을 수행하고 사용자 인증과 권한 확인 또한

소스에 넣어서 요청을 처리한다.
3.3 커스텀 UserDetailsService 인증 적용
스프링 시큐리티에서 제공하는 테이블이나 타입이 맞지 않더라도 UserDetailsService인터페이스의 구현체를 만들어 등록하면 스프링 시큐리티가 제공하는 인증 서비스를 이용할 수 있다.

UserDetailsService 구현체를 만들어서 User클래스와 직접 매핑해준다.
그 후 SecurityConfiguration 클래스에 UserDetailsService 구현체를 빈으로 등록하면 동일하게 사용이 가능하다.

3.4 LDAP 인증 적용
조회가 매우 자주 발생하는 사용자 인증이니만큼 다른 방식에 비해 조회가 더 빠른 LDAP인증은 보편적으로 많이 사용된다.
LDAP인증을 적용하기 위해서는 먼저 의존관계를 넣어줘야 한다.

ldap-core, security-ldap은 필수적으로 필요하고 ldapsdk는 내장형 ldap서버로 외장 서버가 있으면 추가 할 필요 없다.

LDAP을 활용한 인증 코드로 순서대로
- LDAP인증 적용 선언
- DN정보로 미리 설정한 .ldif파일 정보와 일치해야 한다.
- 호출하는 LDAP서버 정보
- 패스워드가 동일해야 인증 성공
- 패스워드 암호화 인코딩으로 예제에서는 비밀번호를 암호화 하지 않아서 NoOpPasswordEncoder를 입력했다.
- 비밀번호 속성을 지정해야 하는데 이 또한 .ldif파일과 동일해야 한다.
3.5 HTTP 인증 적용
폼 기반 인증이 아니라 스프링 시큐리티에서 기본적으로 제공하는 HTTP 기본 인증을 사용한 방식이다.

모든 요청이 http기본 인증을 거치도록 설정하면

로그인 페이지가 아니라 브라우저 다이얼로그 창이 떠서 아이디와 PW 입력을 기다린다.
'책 리뷰 > Spring Boot in Practice' 카테고리의 다른 글
| 8. 리액티브 스프링 부트 애플리케이션 개발 (0) | 2025.02.09 |
|---|---|
| 2. 스프링 부트 공통 작업 (0) | 2024.12.02 |
| 1. 스프링 부트 시작하기 (3) | 2024.12.02 |