📙Spring Security
✏️Spring Security란?
- 인증, 권한 관리, 데이터 보호 기능을 포함하여 웹 개발 과정에서 필수적인 사용자 관리 기능을 구현하는데 도움을 주는 Spring의 프레임워크이다.
- 개발자들이 보안 관련 기능을 효율적이고 신속하게 구현할 수 있도록 도와준다.
✏️Spring Security를 사용하는 이유
- Spring의 생태계에서 보안에 필요한 기능들을 제공
- 개발 구조가 Spring이라는 프레임워크 안에서 활용하기 적합한 구조로 설계되어 있어, 보안 기능을 추가할 때 활용하기 좋다.
- IoC/DI 패턴과 같은 확장 패턴을 염두해서 인증/인가 기능을 제공해주기 때문에 개발 작업 효율을 높일 수 있다.
✏️Spring Security 아키텍처

- 서버에 사용자가 요청한다.
- Authentication Filter가 요청을 가로채고, Authentication Manager로 요청을 위임한다.
- Authentication Manager는 등록된 Authentication Provider를 조회하며 인증을 요구한다.
- Authentication Provider가 실제 데이터를 조회하여 UserDetails 결과를 돌려준다.
- 결과는 SecurityContextHolder에 저장되어 저장된 유저정보를 Spring Controller에서 사용할 수 있게 된다.
주요 컴포넌트들의 특징을 살펴보자.
- Authentication Filter
- 사용자의 인증 요청을 가로채고 처리한다.
- 폼 기반 로그인에서 사용자명과 비밀번호를 추출한다.
- 추출된 정보로 Authentication 객체를 생성하고 Authentication Manager에게 인증을 위임한다.
- Authentication Manager
- 실제 인증을 수행하는 인터페이스
- Authentication Provider를 관리하고, 적절한 Provider를 선택하여 인증을 위임한다.
- Authentication Provider
- 실제 인증 로직을 구현하는 컴포넌트
- UserDetailsService를 통해 사용자 정보를 조회하고 비밀번호를 검증한다.
- UserDetails
- 인증에 필요한 사용자 정보를 담는 인터페이스
- 사용자의 이름, 비밀번호, 권한 등의 정보를 포함
- SecurityContextHolder
- 인증된 사용자의 정보를 저장하고 관리
- ThreadLocal을 사용하여 현재 스레드에서 인증 정보에 접근할 수 있게 한다.
- Spring Controller
- 인증 후 실제 비즈니스 로직을 처리하는 컴포넌트
- SecurityContextHolder에서 인증된 사용자 정보를 가져와 사용할 수 있다.
✏️Spring Security가 작동하는 내부 구조

- 사용자가 자격 증명 정보를 제출하면, AbstractAuthenticationProcessingFilter가 Authentication 객체를 생성한다.
- Authentication 객체가 AuthenticationManager에게 전달된다.
- 인증에 실패하면, 로그인 된 유저정보가 저장된 SecurityContextHolder의 값이 지워지고 RememberMeService.joinFail()과 AuthenticationFailureHandler가 실행된다.
- 인증에 성공하면, SessionAuthenticationStrategy가 새로운 로그인이 되었음을 알리고, Authentication이 SecurityContextHoler가 저장된다.
SecurityContextPersistenceFilter가 SecurityContext를 HttpSession에 저장하면서 로그인 세션 정보가 저장된다.
- RememberMeServices.loginSuccess()가 실행된다.
ApplicationEventPublisher가 InteractiveAuthenticationSuccessEvent를 발생시키고, AuthenticationSuccessHandler가 실행된다.
주요 컴포넌트들의 특징을 살펴보자
- AbstractAuthenticationProcessingFilter
- 인증 처리
- UsernamePasswordAuthenticationFilter 등 구체적인 인증 필터들의 상위 클래스
- Authentication
- 인증 정보를 담는 인터페이스
- 인증 전후의 사용자 정보와 권한 정보를 포함
- RememberMeService
- "Remember Me" 기능을 구현하는 서비스
- joinFail() 메서드 : 인증 실패 시 호출되어 관련 처리를 수행
- AuthenticationFailureHandler
- 인증 실패 시 호출되는 핸들러
- 실패 시의 로직을 구현
- SessionAuthenticationStrategy
- 새로운 로그인 세션을 관리하는 인터페이스
- 세션 고정 보호, 동시 세션 제어 등을 담당
- SecurityContextPersistenceFilter
- SecurityContext를 HTTP 세션에 저장하고 복원
- 요청 간 인증 정보를 유지
- HttpSession
- 사용자의 세션 정보를 저장하는 객체
- SecurityContext를 저장하여 요청 간 인증 상태를 유지
- ApplicationEventPublisher
- 스프링의 이벤트 발행 메커니즘을 사용하는 인터페이스
- 인증 관련 이벤트를 발행
- AuthenticationSuccessHandler
- 인증 성공 시 호출되는 핸들러
- 성공 후의 로직을 구현
📙OAuth2
Spring Security는 OAuth2 프로토콜을 지원한다. 이를 통해 소셜 미디어 플랫폼의 인증을 구현할 수 있다.
✏️OAuth2란?
- 사용자가 자신의 계정 정보를 직접 공유하지 않고도 다른 애플리케이션에 특정 리소스에 대한 접근 권한을 안전하게 부여할 수 있게 해준다.
- 제3자 애플리케이션이 사용자를 대신해 HTTP 서비스를 이용할 수 있는 권한을 부여한다.
✏️OAuth2를 사용하는 이유
- 보안성
- 유연성
- 다양한 클라이언트 환경에 적합한 인증 및 권한 부여 방식을 제공한다.
- 사용자의 편의성
- 사용자는 한 번 로그인하여 다른 서비스에서 자신의 정보를 사용할 수 있도록 허용하면, 해당 서비스에 다시 로그인 하지 않아도 된다.
✏️OAuth2를 사용하여 소셜 로그인을 구현하기 위해서는?
- 의존성 추가
- spring-boot-starter-oauth2-client 의존성을 추가한다.
- application.properties 설정
- 소셜 로그인 제공자의 클라이언트 ID와 시크릿을 설정한다.
- SecurityConfig 설정
- SecurityFilterChain을 구성하여 소셜 로그인을 활성화한다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.oauth2Login()
.userInfoEndpoint()
.userService(customOAuth2UserService);
return http.build();
}
- CustomOAuth2UserService 구현
- 소셜 로그인 후 사용자 정보를 처리하는 서비스를 구현
✏️Spring Security의 OAuth2 인증 과정

- 사용자가 소셜 로그인 요청을 보낸다.
- OAuth2LoginAuthenticationFilter가 요청을 가로챈다.
- AuthenticationManager가 OAuth2LoginAuthenticationProvider를 통해 인증을 처리한다.
- 인증이 성공하면, OAuth2User 객체가 생성되어 SecurityContextHolder에 저장된다.
- CustomOAuth2UserService에서 소셜 플랫폼에서 받은 사용자 정보를 처리한다.
- AuthenticationSuccessHandler가 로그인 성공 후 처리를 담당한다.
주요 컴포넌트들의 특징을 알아보자.
- OAuth2LoginAuthenticationFilter
- " /login/oauth2/code/* " URL 패턴의 요청을 처리한다.
- 인증 코드를 이용해 액세스 토큰을 발급받고, 사용자 정보를 요청한다.
- OAuth2AuthenticationToken을 생성하여 반환한다.
- AuthenticationManager
- 적절한 AuthenticationProvider를 선택하여 인증을 위임한다.
- OAuth2 인증의 경우 OAuth2LoginAuthenticationProvider를 선택한다.
- OAuth2LoginAuthenticationProvider
- OAuth2 인증 서버에 코드를 전달하여 액세스 토큰을 받아온다.
- 액세스 토큰을 사용해 리소스 서버에서 사용자 정보를 가져온다.
- OAuth2User
- Spring Security에서 UserDetails 역할을 대신한다.
- 소셜 플랫폼에서 제공하는 사용자 정보를 담고 있다.
- SecurityContextHolder
- 인증된 사용자의 정보(OAuth2AuthenticationToken)를 저장하고, 필터나 컨트롤러에서 인증 정보를 전역적으로 접근할 수 있게 한다.
- CustomOAuth2UserService
- 소셜 플랫폼에서 받은 사용자 정보를 애플리케이션에 맞게 처리한다.
- 필요한 경우 추가적인 사용자 정보 매핑이나 데이터베이스 작업을 수행할 수 있다.
- AuthenticationSuccessHandler
- 인증 성공 후의 로직을 처리한다.(특정 페이지로 리다이렉트, JWT 토큰을 생성하여 응답)
📙Spring Security + OAuth2 + JWT
-
사용자가 소셜 로그인 요청을 보낸다.
-
OAuth2LoginAuthenticationFilter가 요청을 가로챈다.
-
AuthenticationManager가 OAuth2LoginAuthenticationProvider를 통해 인증을 처리한다.
-
인증이 성공하면, OAuth2User 객체가 생성되어 SecurityContextHolder에 저장된다.
-
CustomOAuth2UserService에서 소셜 플랫폼에서 받은 사용자 정보를 처리한다.
-
AuthenticationSuccessHandler에서 다음과 같은 JWT 관련 처리를 수행한다.
- JWT Access Token과 Refresh Token을 생성한다.
- Access Token은 짧은 유효기간으로, Refresh Token은 긴 유효기간으로 설정한다.
- 생성된 토큰들을 클라이언트에게 응답으로 전송한다.
💡OAuth2에서 제공하는 액세스 토큰 대신 JWT를 사용하면, 서버에서 자체적으로 토큰을 관리하고 검증할 수 있어 보안성을 높일 수 있다.
-
클라이언트는 받은 JWT를 저장하고, 이후 요청 시 HTTP 헤더에 포함하여 전송한다.
-
서버는 요청을 받을 때마다 JWT를 검증하여 사용자 인증을 수행한다.

참고 자료
https://www.elancer.co.kr/blog/detail/235
https://velog.io/@minnim1010/Spring-Security%EC%9D%98-OAuth2-%EC%9D%B8%EC%A6%9D-%EB%8F%99%EC%9E%91-%EA%B3%BC%EC%A0%95
https://kingofbackend.tistory.com/227#google_vignette
https://kimsy8979.tistory.com/2