[Springboot] Spring Security web ignore 설정

🤯

REST API를 통해 싱글 페이지 애플리케이션을 구현하면서 페이지를 전환할 때마다 권한 관련 처리를 어떻게 해주어야 할지 고민했다.

 

현재 내가 활용하고 있는 방법은 이렇다.

클라이언트에서 페이지를 이동할 때, 라우터 가드에서 이를 가로챈다.

로컬 상태에 있는 토큰으로, 없으면 없는 채로 api에 요청을 보낸다.

api는 시큐리티 필터를 통해 토큰의 유무와 그 유효성을 따지고, 다음 중 하나의 결과를 응답한다.

  1. 인증 상태
    로컬 상태에 토큰이 있고, 그 토큰이 만료되지 않은 로그인 상태
    인증이 필요한 페이지(마이페이지 등)라면 그대로 이동
    미인증 상태를 요구하는 페이지(회원가입, 로그인 등)라면 404 에러페이지
  2. 인증 만료 상태
    로컬 상태에 토큰이 있지만 그 토큰이 만료된 상태
    901 에러를 반환하고 로그인 페이지로 리턴
  3. 비인증 상태
    로컬 상태에 토큰이 없는 비로그인 상태
    인증이 필요한 페이지라면 로그인 페이지로 리턴

 

그런데 간과한 부분이 있었다.

한번의 페이지 이동에서는 한번의 검증만 이루어지면 되는데, 메인 페이지에서 필터가 무려 5번이나 동작하는 것이었다.

처음엔 클라이언트단에서 실수가 있었겠거니 했다.

하지만 컨트롤러에서 로그를 찍어보면 인증에 대한 요청은 한번만 이루어지는게 틀림이 없었다.

 

그래서 이번에는 모든 요청이 통과해야 하는 시큐리티 필터에서 로그를 찍어보았다.

// JwtAuthorizationFilter.java

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
    logger.info("토큰 검증");
    logger.info(request.getRequestURI());

 

vue 프로젝트 빌드를 위한 js, ico 파일들이 필터를 거치고 있는 것을 확인할 수 있었다.

문제는 여기였던 것이다.

Web Ignore

기본적으로 스프링 시큐리티는 자원에 접근하는 모든 요청에 대해 인증, 인가 처리를 한다.

하지만 사진이나 js, css 파일과 같은 정적 자원의 경우, 굳이 시큐리티 필터를 사용해 접근 권한을 확인할 필요가 없다.

스프링 시큐리티에서는 특정 리소스에 대해 필터를 거치지 않고 접근할 수 있도록 설정할 수 있다.

WebSecurityConfigurerAdapter

스프링 시큐리티 설정은 WebSecurityConfigurerAdapter을 상속해 관련 메서드들을 오버라이딩하는 방식으로 할 수 있다.

이 경우 configure()을 통해 web ignore 설정을 해줄 수 있다.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/resources/**"); 
	}
}

하지만 WebSecurityConfigurerAdapter은 Spring Security 5.7.x부터 지원이 중단되었다.

이후 버전부터는 다른 방법을 사용해야 한다.

WebSecurityCustomizer

5.7.x 이후 스프링 시큐리티 설정은 config 클래스에 관련 빈을 등록하는 방식으로 이루어지고 있다.

특정 리소스를 필터에서 제외하기 위해서는 WebSecurityCustomizer 빈을 사용할 수 있다.

// SecurityConfig.java

@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
    return (web) -> web.ignoring().requestMatchers("/static/**");    // 정적 저장소에 접근하면 시큐리티 설정을 무시하도록 함
}

 

이제 정적 자원에 대해 시큐리티 필터가 동작하지 않게 되었다 😄