맞는데 왜 틀릴까..?

Spring Boot/Spring Security

[Spring Security] 기본 / 사용자 정의 보안 기능 구현

안도일 2023. 3. 31. 21:04

 

Spring Security는 form 인증 방식과 jwt 토큰 인증 방식 모두 제공한다.

form 인증 방식은 비교적 쉽게 구현할 수 있을 것 같지만 내 기억으로는 보안에 취약했던 것 같다.

그래서 작년 DRF로 개발을 진행할 때 JWT 토큰 인증 방식을 구현했었는데 로그아웃 부분이 상당히 까다로워서 고생했던 기억이 있다. 과연 Spring Security는 어떨까? 

 


 

일단 Spring Security에는 여러 가지 상속 클래스가 있는데 클래스 명이 매우 길고 다양하다. 따라서 클래스 명에 붙은 의미를 먼저 이해해 보자. 지극히 글쓴이 관점으로 나눈 것이기 때문에 틀릴 수 있는 분류입니다.

 

Filter

 

Web Application에서 Filter는 HTTP 요청을 가로채어서 처리하는 컴포넌트로, HTTP 요청 전후로 처리해야 하는 작업을 처리할 수 있다.

ex) HTTP 요청에 대한 인증, 권한 검사, 요청 파라미터 변환 등의 작업을 처리할 수 있다.

 

Filter는 일반적으로 Servlet Container 내에서 작동하며. 여러 개의 Filter를 체인 형태로 연결하여 사용할 수 있다.

이렇게 체인으로 연결된 Filter는 HTTP 요청이 발생할 때마다 순서대로 처리되는며 웹 애플리케이션 전역에서 사용된다.

 

Spring Security에서는 HTTP 요청을 처리하는 과정에서 여러 개의 Filter를 사용한다.

ex) UsernamePasswordAuthenticationFilter는 로그인 인증을 처리하는 Filter이고, LogoutFilter는 로그아웃 인증을 처리하는 Filter이다. 이러한 Filter는 FilterChainProxy를 통해 체인으로 연결되어 동작하며, FilterChainProxy는 모든 HTTP 요청에 대해 Filter 체인을 실행한다.

 

 

 

Adapter

 

Adapter는 인터페이스를 구현하는 클래스이며, 해당 인터페이스의 모든 메서드를 빈 구현으로 제공하는 클래스를 말한다.

이를 통해 인터페이스의 메소드 중 필요한 것만 오버라이딩 하여 사용할 수 있다.

 

빈(Empty) 구현
아무런 로직이나 동작을 수행하지 않고 메소드 시그니처만 가지고 있는 구현 클래스

 

ex) Spring Security에서 SecurityConfigurer 인터페이스를 구현하기 위한 클래스 중에서 SecurityConfigurerAdapter 같은 Adapter 클래스가 있다.

 

이 클래스들은 인터페이스의 모든 메소드를 빈 구현으로 제공하며, 필요한 메서드만 오버라이딩 하여 사용할 수 있도록 해주어서 코드의 재사용성과 확장성을 높일 수 있다.

 

 

Provider

 

Provider는 Spring Security에서 인증 처리를 수행하는 클래스이다. 

AuthenticationProvider 인터페이스를 구현하여 만들 수 있으며. 인증 처리를 위해 AuthenticationManager에서 사용된다.

 

Spring Security에서 지원하는 Provider 클래스들은 다양한 인증 방식을 지원한다.

ex) DaoAuthenticationProvider는 DB에서 사용자 정보를 가져와 인증 처리를 수행하는 구현체이고.

JwtAuthenticationProvider는 JWT 토큰을 이용한 인증 처리를 수행하는 구현체이다.

 

각각의 Provider 클래스는 인증 처리에 필요한 정보를 제공하는 UseDetailsService나 JwtToeknProvider와 같은 다른 클래스 들과 함께 사용된다.

 


 

사용자 정의 보안 기능 구현

 

HttpSecurity를 구성하기 위한 메서드를 제공하는 WebSecurityConfigurerAdapter 추상 클래스를 상속받아 사용자 정의 보안 기능을 구현하는 SecurityConfig 클래스를 만들어 보자.

 

 

HttpSecurity

 

HttpSecurity 클래스는 Spring Security에서 가장 중요한 클래스 중 하나이며, Spring Security의 대부분의 보안 설정을 수행하는 데 사용된다.

 

인증과 인가에 관한 여러 가지 api를 제공하여 이를 적절히 활용하여 Spring Security에서 필요한 인증과 인가를 설정할 수 있다.

 
WebSecurityConfigurerAdapter 클래스에서 configure(HttpSecurity http) 메서드를 오버라이딩 하여 사용된다.

 

 

 

WebSecurityConfigurerAdapter

 

WebSecurityConfigurerAdapter 클래스는 Spring Security에서 보안 구성을 간단하게 구현할 수 있도록 지원하는 클래스이다. 해당 클래스를 상속받은 구현체에서는 configure(HttpSecurity http) 메서드를 구현해야 한다. 

이 메서드는 Spring Security의 가장 핵심적인 부분인 HttpSecurity 객체를 인자로 받아서 해당 객체를 통해 다음과 같은 보안 구성을 수행할 수 있다.

 

  • 인증 관련 구성(로그인 페이지, 로그인 프로세스, 로그아웃 처리 등)
  • 권한 관련 구성(접근 제한, 권한 계층 등)
  • CSRF(Cross-site request forgery) 공격 방지 구성
  • 세션 관리 구성
  • 기타 다양한 보안 구성

 

configure()

configure() 메서드는 Spring Security의 WebSecurity 객체를 통해 보안 구성을 수행하는 데 사용된다.
이 메서드를 사용하여 보안 구성을 추가하고 필요에 따라 사용자 정의 보안 구성을 추가할 수 있다

 

 

SecurityConfig

 

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().authenticated()
        .and()
                .formLogin()
                .loginPage("/loginPage") // 사용자 정의 로그인 페이지
                .defaultSuccessUrl("/") // 로그인 성공 후 이동 페이지
                .failureUrl("/login") // 로그인 실패 후 이동 페이지
                .usernameParameter("userId") // 아이디 파라미터명 설정
                .passwordParameter("passwd") // 패스워드 파라미터명 설정
                .loginProcessingUrl("/login_proc") // 로그인 Form Action Url
                .successHandler(new AuthenticationSuccessHandler() { // 로그인 성공 후 핸들러
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                        System.out.println("authentication = " + authentication.getName());
                        response.sendRedirect("/");
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() { // 로그인 실패 후 핸들러
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
                        System.out.println("exception = " + exception.getMessage());
                        response.sendRedirect("/login");
                    }
                })
                .permitAll(); // 사용자 정의 로그인 페이지 접근 권한 승인
    }
}

 

@Configuration

@Configuration 어노테이션은 해당 클래스가 스프링 컨텍스트에게 Bean 정의를 제공하는 구성 클래스임을 나타낸다. 

즉, 이 클래스가 Bean으로 인식되어 스프링 컨테이너에서 사용될 수 있도록 하는 역할을 한다.

이 코드에서 SecurityConfig 클래스는 Spring Security 설정을 담당하는 구성 클래스이므로 @Configuration 어노테이션을 사용하여 스프링 컨테이너에서 해당 클래스를 Bean으로 등록하도록 지정한 것이다.

 

@EnableWebSecurity

@EnableWebSecurity는 Spring Security의 웹 보안을 활성화하기 위한 어노테이션이다. 이 어노테이션은 WebSecurityConfigurerAdapter 클래스를 상속받은 설정 클래스에서 사용되며, 이 설정 클래스가 @Configuration 어노테이션을 가지고 있어야 한다.

또한. 이 어노테이션을 사용하면 SpringSecurityFilterChain을 등록하게 된다. 이 필터 체인은 웹 보안을 위해 다양한 필터들을 포함하고 있으며, 이를 통해 인증, 인가, 로그인 등의 웹 보안 기능을 구현할 수 있다.