SpringSecurity (2)

 

 

 

 

 

 

🍙 Spring Security의 인증 처리 흐름

 

 

Authentication flow

 

 


 

 

🍙 Authentication(인증)

 

 

🍘 Authentication 인터페이스

 

🍥 Spring Security에서 Authentication은 인터페이스로 존재한다.

🍥 사용자가 인증을 성공적으로 수행하면 사용자의 인증정보를 가지고 있는다.

🍥 SecurityContextHolder는 SecurityContext를 호출하고 SecurityContext는 Authentication 객체를 갖고 있다.

🍥 일반적으로 많이 사용하는 구현체는 UsernamePasswordAuthenticationToken 이다.

➡️ 사용자의 고유 식별자(Username)과 암호(Password)로 간단하게 Authentication 객체를 생성할 수 있다.

 

 

🍘 Spring Security내에서의 Authentication 주요 목적

 

  • 사용자가 인증을 위해 제공한 Credential(자격증명)을 제공하기 위해 AuthenticationManager에 대한 입력값이다.
  • 현재 인증된 사용자를 나타낸다. 현재 Authenticaion은 SecurityContext에서 얻을 수 있다.

 

 

 

🍘 Authentication 에 포함된 정보

 

🍰 principal

  • 사용자를 식별한다.
  • UserDetails 인터페이스 구현체는 사용자의 username과 password로 인증이 이루어진다.
  • 구현체 위치 : org.springframework.security.core.userdetails.User
  • 직접 UserDetails를 상속받아 구현할 수도 있다.

 

🍰 credentials

  • 대부분 password 이다.
  • 대부분의 경우 사용자 안증 후에 유출되지 않도록 삭제된다.

 

🍰 authorities

  • AuthenticationManager에 의해 부여된 인가에 대한 정보이다.
  • 부여된 권한에 대한 정보는 GrantedAuthority로 추상화한다.
  • 일반적으로 사용하는 구현체는 SimpleGrantedAuthority 이다.

 

 

 

🍘 Spring Security 에서 Authentication

 

  • Spring Security 는 종합적인 인증처리를 지원한다.
  • 인증은 특정 리소스에 접근하려고 하는 사용자가 누구인지 확인할 때 사용한다.
  • 보통 사용자가 이름과 비밀번호를 입력하는 것으로 사용자를 인증한다.
  • 한번 인증하면 사용자를 식별하고 권한을 부여할 수 있다. (Authorization, 인가)

 

 

 

🍘 Password Storage

 

Spring Security의 PasswordEncoder 인터페이스는 비밀번호를 안전하게 저장할 수 있도록 단방향 변환을 수행해준다.

  • PasswordEncoder 는 비밀번호를 단반향(비밀번호 -> 암호화)으로 변환, 양방향 변환 목적 x
  • 인증에 사용할 credential 정보를 저장한다.

PasswordEncoder 를 사용해서 저장하는 비밀번호는 인증 시점에 사용자가 입력하는 비밀번호와 비교하는 용도이다.

 

 

 

🍘 Password Storage History

 

패스워드를 저장하는 표준 매커니즘의 변화

 

🍰 처음에는 일반 텍스트로 암호를 저장했다.

  • 비밀번호를 담고 있는 DB에 접근하려면 credential이 필요했기 때문에 비밀번호가 안전하다고 생각했다.
  • 악의적인 SQL Injection 같은 공격으로 “Data dump”를 읽어갈 수 있는 방법이 존재한다.

 

🍰 암호를 저장하기 전에 SHA-256 같은 단방향 해시를 실행한 후 암호를 저장했다.

  • 사용자가 인증을 시도할 때 입력한 암호를 해시 처리하여 저장된 비밀번호와 입력한 비밀번호의 해시값을 비교한다.
  • 시스템에선 비밀번호의 단방향 해시만 저장하면 됐다.
  • 악의적인 공격으로 정보가 유출이 되더라도 실제 비밀번호가 아닌 비밀번호의 단방향 해시값만 알 수 있다.
  • 단방향 해시값만으로 비밀번호를 추측하기는 불가능에 가까웠다.
  • 하지만 레인보우 테이블로 알려진 룩업 테이블이 만들어지면서 안전하지 않게 됐다.

 

🍰 레인보우 테이블을 무력화하기 위해 솔티드 패스워드(salted password)를 사용했다.

  • 비밀번호 해시 함수 ➡️ 모든 사용자의 비밀번호로 랜덤 바이트(솔트)를 만들었다.
  • 솔트와 사용자의 비밀번호로 해시 함수를 실행하면 유니크한 해시값을 생성한다.
  • 솔트는 유니크하기 때문에 솔트와 비밀번호 조합은 레인보우 테이블을 무력화할 수 있었다.
  • 하지만 기술이 발전함에 따라 최신 하드웨어를 사용하면 초당 수십억 건을 계산할 수 있게 되며 비밀번호를 쉽게 해독할 수 있어 SHA-256같은 해시가 더 이상 안전하지 않게 되었다.

 

🍰 현재는 적응형 단방향 함수(adaptive one-way function)로 비밀번호를 저장하는 것을 권장한다.

  • CPU, 메모리 등 많은 리소스를 소모해서 비밀번호를 검증 ➡️ 애플리케이션 성능이 크게 떨어질 수 있다.
  • 적응형 단방향 함수는 하드웨어 사양에 따라 work factor를 구성할 수 있다.
  • 워크 팩터(work factor) : 공격자가 암호를 깨는데 드는 노력, 시스템에서 비밀번호를 검증할 때 소요되는 시간과 관련있다.
  • 공격자가 쉽게 비밀번호를 해독하지 못하게 만들지만 시스템 자체에 부담이 된다.
  • Spring Security 는 work factor 시작점을 제공하지만 성능에 따라 각자의 시스템에 맞게 설정하는게 좋다.
  • 종류 : bcrypt, PBKDF2, scrypt, argon2
  • 사용하는 부분에서 장기 자격 증명(사용자 이름및 암호)에서 단기 자격 증명(세션, OAuth 토큰 등)으로 바꾸는게 좋다. ➡️ 단기 자격 증명은 동일한 보안 수준을 유지하면서도 빠르게 검증할 수 있다.

 

 


 

 

🍙 Servlet Authentication Architecture

 

 

🍘 Architecture

 

Servlet authentication에서 사용하는 Spring Security의 구성요소

 

🍰 SecurityContextHolder

Spring Security가 인증한 대상에 대한 디테일을 저장하는 곳이다.

SpringContextHolder

 

 

🍰 SecurityContext

SecurityContextHolder에서 가져와진다. 현재 인증된 사용자의 인증을 포함한다.

 

 

🍰 Authentication

AuthenticationManager의 입력으로 사용된다.

사용자 인증을 위해 제공한 credential이나 SecurityContext에 있는 현재 사용자의 credential을 제공한다.

Authentication이 가지고 있는 정보들

  • principal : 사용자를 식별한다. username/password로 인증할 때 주로 UserDetails의 인스턴스를 이용한다.
  • credentials : 일반적으로 password를 사용한다. (유출되지 않도록 인증 후 비운다.)
  • authorities : 사용자에게 부여한 권한은 grantedAuthority로 추상화한다.

 

 

🍰 GrantedAuthority

Authentication에서 principal(주체)에게 부여된 authority(권한)이다. (역할, 범위 등)

Authentication.getAuthorities() 메서드는 GrantedAuthority 객체들을 Collection으로 리턴한다.

권한은 보통 역할(roles)이다. (예 : "ROLE_ADMINISTRATOR", "ROLE_HR_SUPERVISOR")

이런 역할들은 나중에 웹 권한 부여, 메서드 권한 부여 및 도메인 객체 권한 부여를 위해 구성된다.

username/password 기반 인증을 사용한다면 UserDetailsServiceGrantedAuthority를 로드한다.

GrantedAuthority 객체는 애플리케이션 전체에 걸친 권한을 의미한다. (특정 도메인으로 한정하는 목적으로 사용하진 않는다.)

 

 

🍰 AuthenticationManager

Spring Seuciry의 필터가 어떻게 인증을 수행하는지에 대한 방법을 정의하는 API이다.

  • AuthenticationManager를 호출한 객체(Filter)가 리턴한 AuthenticationSecurityContextHolder에 설정한다.
  • Spring Security의 Filters를 사용하지 않을 경우 AuthenticationManager를 사용하지 않고 SecurityContextHolder에 직접 설정하면 된다.
  • AuthenticationManager의 가장 많이 사용하는 구현체는 ProviderManager이다.

 

 

🍰 ProviderManager

AuthenticationManager의 가장 일반적인 구현체이다.

  • ProviderManager는 동작을 AuthenticationProvider List에 위임한다.
  • 모든 AuthenticationProvider는 인증을 성공 or 실패 or 결정을 내릴 수 없는 지를 판단하고 다운스트림에 있는 AuthenticationProvider가 결정하게 할 수 있다.
  • 설정한 AuthenticationProvider들 중 어떤 것도 인증할 수 없다면, ProviderNotFoundException 오류와 함께 인증이 실패한다.
  • ProviderNotFoundException : ProviderManager가 전달된 Authentication 유형을 지원하도록 구성되지 않았음을 나타낸다.
  • AuthenticationProvider마다 각자 맡은 인증을 수행한다.

 

ProviderManager

 

  • ProviderManager에 인증을 수행할 AuthenticatinoProvider가 없을 경우, 부모 AuthenticationManager 구성을 허용한다.
  • 부모는 어떤 타입의 AuthenticationManager든 가능하지만 주로 ProviderManager의 인스턴스이다.

 

ProviderManager - AuthenticationManager

 

  • 여러 개의 SecurityFilterChain 인스턴스가 공통의 인증(같은 부모 AuthenticationManager)을 가지지만 다른 인증 매커니즘(다른 ProviderManager 인스턴스)일 경우 같은 부모 AuthenticationManager를 여러 ProviderManager가 공유할 수 있다.

 

multiple ProviderManager

 

  • ProviderManager는 인증 이후의 리턴된 Authentication 객체의 모든 민감한 credential 정보는 제거하려고 시도한다.
  • password와 같은 정보가 HttpSession에 필요 이상으로 오래 남아있는 것을 방지하기 위해서이다.
  • 하지만 Authentication에 cache의 객체(ex. UserDetails)에 대한 참조가 포함되어 있는 경우 credential 정보를 모두 제거하면 캐시된 값에 대해 더 이상 인증할 수 없는 문제가 생길 수 있다.
  • 해결책은 캐시 구현 또는 반환된 Authentication 객체를 생성하는 AuthenticationProvider에서 먼저 객체의 복사본을 만드는 것이다.
  • 또 다른 해결책으로는 ProviderManagereraseCredentialsAfterAuthentication property를 비활성화 하는것이다.

 

 

🍰 AuthenticationProvider

다수의 AuthenticationProviderProviderManager에 주입할 수 있다.

각각의 AuthenticationProvider는 특정 유형의 인증을 수행한다.

ex) DaoAuthenticationProvider : username/password 기반의 인증을 지원한다.

JwtAuthenticationProvider : JWT 토큰 인증을 지원한다.

 

 

🍰 Request Credentials with AuthenticationEntryPoint

AuthenticationEntryPoint는 클라이언트의 자격증명 요청에 대한 응답 HTTP를 보내는데 사용된다.

또한 클라이언트에 자격증명을 요청할 때 사용된다.

AuthenticationEntryPoint의 구현체는 로그인 페이지로 리디렉션하거나 WWW-Authenticate header를 전송하는 것을 수행한다.

 

 

🍰 AbstractAuthenticationProcessingFilter

사용자의 credentials를 인증하기 위한 기초 Filter로 사용된다.

credentials이 인증되기 전에, Spring Security는 일반적으로 AuthenticationEntryPoint를 사용하여 credentials을 요청한다.

여러 component를 조합하여 심도있는 인증 플로우를 구성할 수 있다.

 

 

 

 

참고) Servlet Authentication Architecture

참고) Spring Security doc

 

 

 

감사합니다.

오개념에 대한 지적은 늘 환영입니다. 😃

 

 

 

 

 

 

 

 

 

🥧 Spring Security 란?

 

 

🍞 스프링 시큐리티(Spring Security)

 

Acegi Security(아시지 시큐리티) 프로젝트로 시작

➡️ 스프링 포트폴리오 프로젝트에 병합되면서 이름이 Spring Security로 바뀌었다.

 

🍰 Spring Security는 강력하고 커스텀 가능한 인증(Authentication)과 접근 통제(Access Control) 프레임워크이다.

🍰 스프링 기반의 애플리케이션에서 보안을 위한 표준이다.

🍰 모든 자바 애플리케이션에 적용 가능하지만 웹 애플리케이션에서 많이 쓰인다.

🍰 스프링 인터셉터, 필터 기반의 보안 기능을 구현하는 것보다 스프링 시큐리티를 통해 구현하는 것을 권장하고 있다.

🍰 확장성 : 다양한 요구사항을 손쉽게 추가하고 변경할 수 있다.

🍰 실행하려면 Java 8 이상의 환경이 필요

 

 

 

🍞 필수 용어 및 개념

 

🥞 주체 (Principal)

🍰 유저, 기기, 시스템 등이 될 수 있지만 보통 유저(사용자)를 의미한다.

 

🥞 인증 (Authentication)

🍰 특정 리소스에 접근하려고 하는 사용자가 누구인지 확인할 때 사용한다.

🍰 주체의 신원(identity)을 증명하는 과정

🍰 주체는 자신을 인증해달라고 신원 증명 정보(credential)을 제시한다.

🍰 주체가 유저일 경우 신원 증명 정보는 패스워드이다.

 

🥞 인가 (Authorization, 권한 부여)

🍰 인증을 마친 유저에게 권한(authority)을 부여하여 애플리케이션의 특정 리소스에 접근할 수 있게 허가하는 과정

🍰 인가는 반드시 인증 과정 이후 수행되어야 하며 권한은 롤 형태로 부여하는게 일반적이다.

 

🥞 접근통제 (Access control)

🍰 어떤 유저가 애플리케이션 리소스에 접근하도록 허락할 지를 제어하는 행위

🍰 접근 통제 결정(access control decision)이 뒤따른다.

🍰 리소스의 접근 속성과 유저에게 부여된 권한 또는 다른 속성들을 결정한다.

 

 

 


 

 

🥧 Spring Security를 배워야 하는 이유

 

 

🍞 Spring Security 특징

 

🍰 모든 요청에 대해서 인증을 요구한다.

🍰 사용자 이름 및 암호를 가진 사용자가 양식 기반으로 인증할 수 있도록 허용한다.

🍰 사용자의 logout을 허용한다. ➡️ LogoutFilter로 코드의 구현없이도 간편하게 로그아웃을 지원한다. 커스텀도 가능하다.

🍰 CSRF(Cross-site Request Forgery) 공격을 방지한다.

🍰 Session Fixation(세션 고정 공격)을 보호한다.

🍰 보안 헤더 통합

  • HSTS(HTTP Strict Transport Security) 강화
  • X-Content-TypeOptions
  • 캐시 컨트롤(정적 리소스 캐싱)
  • X-XSS-Protection XSS 보안 : 스크립트 공격 보안
  • 클릭재킹을 방지하는 X-Frame 옵션 통합

🍰 Servlet API 제공

 

 

※ Session Fixation (세션 고정 공격)

세션 고정이란 공격자가 유효한 사용자 세션을 가로채도록 허용하는 공격을 말한다.

로그인 시 발급받은 sessionID가 로그인 전후로 모두 동일하게 사용되어 악의적인 사용자가 피해자의 세션을 하이제킹하여 정상적인 사용자로 위장하여 접근한다.

공격자가 유효한 session ID를 얻음 ➡️ 사용자가 공격자의 session ID로 자신을 인증하도록 유도 ➡️ 사용된 session ID를 통해 사용자 검증된 세션을 하이재킹

세션에 대한 만료나 서로 다른 IP의 동일한 세션에 대해 취약한 웹 애플리케이션의 경우 이용하는 다수의 사용자가 해당 공격에 노출될 가능성이 존재한다.

 

참고) OWASP

참고) Session Fixation(세션 고정) 취약점

 

 

※ HSTS(HTTP Strict Transport Security) 기능

HTTP Strict-Transport-Security response header

HTTP 대신 HTTPS만을 사용하여 통신해야한다고 웹사이트가 브라우저에 알리는 보안 기능이다.

통신에서 일부분 HTTP를 사용할 경우 sessionID나 쿠키등이 해커에게 탈취되었을 경우 그대로 데이터가 노출이 되지만 HTTPS를 사용할 경우엔 데이터가 노출되는 것을 막을 수 있다.

만약 웹사이트가 HTTP 요청을 받고 HTTPS로 리다이렉트 하는 경우에, 유저가 http 또는 도메인만 입력한 경우에 리다이렉트 되기 이전의 암호화되지 않은 버전의 사이트와 통신하게 된다. 이경우, 악의적인 다른 페이지로 리다이렉트 되는 man-in-the-middle attack의 잠재적 위험이 있다.

HTTP Strict Transport Security 헤더는 웹사이트가 브라우저에게 절대로 HTTP로 사이트를 연결하면 안되고 HTTP로 연결하려는 모든 시도는 자동으로 HTTPS로 변경해야 한다고 알린다.

 

참고) mdn web docs

참고) HSTS

 

 

※ 클릭재킹

클릭재킹이란 웹 사용자가 자신이 클릭하고 있다고 인자하는 것과 다른 것을 클릭하게 속이는 해킹 기법이다.

공격자는 비밀 정보를 유출시키거나 컴퓨터에대한 제어를 획득할 수 있게 된다.

 

 

※ Cache-Control

header 필드

request와 response 내의 캐싱 정하기 위해 사용된다.

 

 

참고) mdn web docs

 

 


 

 

🥧 Spring Security 환경 구성

 

config 패키지와 SecurityConfig.java 파일 생성

 

  • @Configuration , @EnableWebSecurity 추가
  • @EnableWebSecurity : spring security 필터체인에 등록된다.

 

 

🥞 http.csrf().disable()

form 태그로만 요청이 가능하고 postman 등의 요청이 불가능하게 된다.

 

 

🥞 http.headers().frameOptions().disable()

h2 연결할 때 필요하다.

 

 

🥞 BCryptPasswordEncoder 클래스

PasswordEncoder를 구현한 클래스이고 강력한 해시 함수인 BCrypt 를 사용한다.

 

※ 참고) bcrypt

블로피시 암호에 기반을 둔 암호화 해시 함수

레인보우 테이블 공격 방지를 위해 salt를 추가한 적응형 함수의 하나이다.

 

 

🥞 @EnableGlobalMethodSecurity

Spring Security 의 전역 메서드 보안을 활성화한다.

 

✅ 옵션

1. securedEnabled : Secured 애너테이션 활성화 여부를 결정한다.

2. prePostEnabled : Spring Security의 pre/proAuthorize 애너테이션을 활성화한다.

3. jsr250Enabled : @RoleAllowed 애너테이션을 사용할 수 있도록 해준다.

 

 

🥞 @Secured

1개의 권한을 줄 때 사용

@Secured(“ROLE_ADMIN”)

 

 

🥞 @PreAuthorize

 

1개 이상의 권한을 줄 때 사용

#을 이용해서 파라미터에 접근할 수 있다.

 

@PreAuthorize(“hasRole(‘ROLE_MANAGER’) or hasRole(‘ROLE_ADMIN’)”)

 

@PreAuthozie(“isAuthenticated() and ((#user.name == principal.name) or hasRole(‘ROLE_ADMIN’))”)

 

 

 

🥞 @PostAuthorize

 

메서드가 실행되고 응답하기 직전에 권한을 검사하는데 사용

클라이언트에 응답하기 전에 로그인 상태 또는 반환되는 사용자 이름과 현재 사용자 이름에 대한 검사, 현재 사용자가 관리자 권한을 가지고 있는지 등의 권한 후처리를 한다.

 

 


 

 

🥧 Filter와 FilterChain

 

 

🍞 Filter

 

Spring Filter

 

Spring Security는 Servlet Filter를 기반으로 서블릿을 지원한다.

Filter : HTTP 요청과 응답을 변경할 수 있는 재사용 가능한 코드이다.

 

  • 클라이언트가 서버로 요청을 하게되면 가장 먼저 Servlet Filter를 거치게 된다.
  • Filter를 거치고 나면 Servlet(DispatcherServlet)에서 요청이 처리된다.
  • Spring Security는 주요 보안에 대한 처리를 여러가지 Filter로 처리하도록 구성되어 있다.
  • 인증(Authentication)과 인가(Authorization)에 대한 처리를 Filter에서 한다.
  • 자동 설정 옵션을 사용하면 10개의 스프링 시큐리티 필터가 자동으로 설정된다.

 

 

 

🍞 FilterChain

 

Filter Chain

 

단일 HTTP 요청을 처리하는 전형적인 레이어

여러개의 Filter들이 사슬처럼 연결되어 서로 연결되어 동작한다.

 

 

🥞 FilterChain의 특징

 

🍰 클라이언트가 앱에 요청을 보내고 컨테이너는 요청 URI의 경로를 기반으로 어떤 필터와 어떤 서블릿을 적용할지 결정한다.

🍰 하나의 서블릿은 단일 요청을 처리하지만 필터는 체인을 형성하여 순서를 지정하며 실제로 요청 자체를 처리하려는 경우 필터가 나머지 체인을 거부할 수 있다.

🍰 필터는 다운스트림 필터와 서블릿을 사용해서 요청과 응답을 수정할 수도 있다.

🍰 필터 체인의 순서는 매우 중요하며 Spring Boot는 두 가지 매커니즘을 통해 이를 관리한다. 하나는 Filter 타입의 @Beans 에 @Order를 붙이거나 Ordered를 구현하는 것이고 다른 하나는 API의 일부로 순서를 가지는 FilterRegistrationBean의 일부가 되는 것이다.

🍰 클라이언트는 애플리케이션으로 요청을 전송하고 컨테이너는 Servlet과 여러 Filter로 구성된 FilterChain을 만들어 요청 URI path 기반으로 HttpServletRequest를 처리한다.

🍰 Filter는 요청이 DispatcherServlet에 의해 다뤄지기 전, 후에 동작한다.

🍰 Filter는 FilterChain을 통해 여러 필터가 연쇄적으로 동작하게 할 수 있다.

🍰 1개의 Servlet이 HttpServletRequest와 HttpServletResponse 처리를 담당한다.

  • Filter는 여러개 사용할 수 있다.
  • 다운 스트림의 Servlet과 Filter의 실행을 막는다. (보통 이 경우 Filter에서 HttpServletResonse를 작성한다.)
  • 다운 스트림에 있는 Servlet과 여러 Filter로 HttpServletRequest나 HttpServletResponse를 수정한다.

🍰 Filter는 FilterChain 안에 있을 때 효력을 발휘한다.

 

 

 

🥞 Filter Interface

 

  • public void init(FilterConfig filterConfig) throws ServletException 필터를 웹 컨테이너 내에 생성한 후 초기화 할 때 호출한다.
  • public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException 체인을 따라 다음에 존재하는 필터로 이동한다.
  • 체인의 가장 마지막에는 클라이언트가 요청한 최종 자원이 위치한다.
  • public void destroy() 필터 : 웹 컨테이너에서 삭제될 때 호출된다.
  • doFilter() : 필터의 역할을 하는 메서드

 

 

 

🥞 FilterRegistrationBean 옵션

 

FilterRegistrationBean의 옵션으로 Filter에 여러가지 옵션을 추가할 수 있다.

 

🥑 addUrlPatterns

registrationBean.addUrlPatterns(“/users/*”);

setUrlPatterns와 비슷하다.

/users/ 로 시작하는 url로 요청이 오게되면 필터를 통과한다.

 

🥑 setOrder

registrationBean.setOrder(1);

필터의 실행 순서를 지정한다.

 

 

 

🍞 DelegatingFilterProxy

 

DelegatingFilterProxy

 

Spring Security가 모든 애플리케이션 요청을 감싸게 해서 모든 요청에 보안이 적용되게 하는 ServletFilter이다.

스프링 프레임워크 기반의 웹 애플리케이션에서 서블릿필터 라이프 사이클과 연계해 스프링 빈 의존성을 서블릿 필터에 바인딩하는데 사용한다.

 

  • 스프링 부트는 DelegatingFilterProxy(Filter 구현체)로 서블릿 컨테이너의 생명주기와 스프링 ApplicationContext를 연결한다.
  • Servlet Container는 자체 표준을 사용해서 Filter를 등록할 수 있지만 스프링이 정의하는 Bean은 인식하지 못한다.
  • DelegatingFilterProxy는 표준 서블릿 컨테이너 매커니즘으로 등록할 수 있으면서도 모든 처리를 Filter를 구현한 스프링 빈으로 위임한다.
  • DelegatingFilterProxy는 ApplicationContext에서 Bean Filter0를 찾아 실행한다.
  • Bean Filter0는 FilterChainProxy가 된다.

 

 

 

🍞 FilterChainProxy

 

Spring Security는 FilterChainProxy로 서블릿을 지원한다.

 

FilterChain Proxy

 

  • FilterChainProxy는 Spring Security가 제공하는 특별한 Filter로 SecurityFilterChain을 통해 여러 Filter 인스턴스로 위임할 수 있다.
  • FilterChainProxy는 빈이기 때문에 보통 DelegatingFilterProxy로 감싸져 있다.
  • DelegatingFilterProxy는 서블릿 필터이며, Spring IOC 컨테이너가 관리하는 Filter Bean을 갖고있다.
  • Filter Bean은 FilterChainProxy이며 이 객체안에서 Security와 관련된 일들이 벌어진다고 생각할 수 있다. (위 그림에서의 DelegatingFilterProxy안에 Bean Filter는 FilterChainProxy가 된다.)

 

순수한 Servlet Filter는 본래 Spring Container 외부에 존재한다.

DelegatingFilterProxy 클래스는 Filter를 Spring Bean으로 사용할 수 있다.

DelegatingFilterProxy 클래스(Filter Class)는 Servlet Filter 사이에 존재하고 Spring Bean으로 등록된 Filter에게 처리를 위임한다.

 

 


 

 

🥧 DelegatingPasswordEncoder

 

 

🍞 DelegatingPasswordEncoder 란?

 

Spring Security 5.0 버전 이전에 PasswordEncoder의 기본값인 NoOpPasswordEncoder는 일반 텍스트 비밀번호를 사용했다.

비밀번호 히스토리 세션을 기반으로 PasswordEncoder 기본값이 이제 BCryptPasswordEncoder 같은 것으로 바뀌었다.

하지만 다음의 3가지 문제가 존재한다.

  • 애플리케이션이 마이그레이션(이식)이 쉽지 않은 옛날 방식으로 비밀번호를 인코딩하는 경우
  • 비밀번호를 저장하기 위한 관행이 다시 변경될 수 있음
  • Spring Security는 프레임워크로서 자주 변경사항을 변경할 수 없다.

 

대신에 Spring Security는 위의 문제를 해결할 DelegatingPasswordEncoder를 도입했다.

  • 비밀번호를 최신 저장 권장방법으로 인코딩되었는지 확인한다.
  • 최신 및 레거시 형식의 암호 유효성 검사를 허용한다.
  • 향후 인코딩 업그레이드를 허용한다.

 

 

참고) Baeldung Spring Method Security

참고) Spring Security doc

 

 

 

감사합니다.

오개념에 대한 지적은 늘 환영입니다. 😁

 

 

1