개발/Spring

[Spring] 특정 URL에서만 작동하는 서블릿 필터 만들기

서해쭈꾸미 2024. 6. 3. 00:55

스프링 개인 과제를 하면서 로그인 기능 구현을 login Api 요청이 들어올 때 Service단에서 구현해두었는데, Servlet Fillter에서 구현해보면 어떨까 싶어서 로그인 및 인증 필터를 만들어보았다.

 

필터는 서버로 모든 요청이 들어올 때 다 거치게 되기때문에 login 필터를 따로 만들어서 login 요청이 들어올 때만 거치고 다른 요청이 들어오면 login필터는 거치지 않도록 설계해야했다. 특정 URL 요청이 들어올 때만 작동하는 필터는 두 가지 방식으로 만들 수 있다.

 

1. WebFilter 어노테이션 사용
2. FilterRegistrationBean 클래스의 addUrlPatterns 사용

 

 

 

WebFilter 어노테이션 사용

 

@WebFilter("/api/user/login")
//@Order(2) 필터가 여러개일 땐 WebFilter로 URL을 제한 할 수 없다.
public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 필터 로직
        chain.doFilter(request, response);
    }

}

 

처음에 WebFilter 어노테이션으로 필터를 만들었는데 설정해둔 URL만 해당 필터를 거치는 게 아니라 모든 URL 요청이 해당 필터를 거쳤다. 알고보니 WebFilter 어노테이션은 필터가 여러개일 때는 제대로 작동하지 않는다는 원인이 있었다. 그래서 2번째 방식으로 필터를 거칠 수 있는 URL을 제한하기로 했다.

 

 

 

 

FilterRegistrationBean 클래스의 addUrlPatterns 사용

 

FilterRegistrationBean은 Spring Framework에서 제공하는 클래스 중 하나로, 서블릿 필터를 등록하고 구성하는 데 사용된다.

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<LoginFilter> loginFilter() {
        FilterRegistrationBean<LoginFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new LoginFilter());
        registrationBean.addUrlPatterns("/api/user/login");
        registrationBean.setOrder(2);
        registrationBean.setName("Login Filter");
        return registrationBean;
    }
}

 

FilterRegistraionBean을 사용하여 필터에 관한 다양한 설정을 해줄 수 있다. 그 중 addUrlPatterns을 사용하여 특정 URL의 요청만 해당 필터를 통과하도록 설정해주었다.

 

 

 

로그인은 Service단에서 구현하는 게 좋을까 ? 필터에서 구현하는 게 좋을까 ?

 

Spring Security를 사용했을 때도 Security는 필터에서 로그인 인증이 구현되어있었고, 비즈니스 로직과 인증/인가 로직을 구분해볼까? 하는 생각에 필터에서 로그인을 한번 구현해보았다. 정답은 없겠지만 두 방식으로 모두 구현해보았을 때, 개인적으로 Service에서 구현하는 게 좀 더 정석적인 느낌이 들었다. 왜냐면 필터는 말 그대로 모든 요청들이 거쳐서 걸러주는 필터의 역할을 해야하는데 login만을 위한 필터를 만들어서 쓰는 건 필터의 정의와는 맞지 않는다는 생각이 들었기 때문이다. 특정 URL에서만 기능하도록 것은 Controller에 URL을 매핑해두고 로직은 Service에서 구현하는 것이 더 정석적이라는 느낌이 들었다.