OncePerRequestFilter, shouldNotFilter And ignore

형기브·2023년 7월 11일
1

SPRING

목록 보기
1/3

문제

OncePerRequestFilter vs permitAll()

  1. 시큐리티를 이용한 인증 인가를 구현하는 과정에서 의문이 생겼다.
    무조건 한번 거치는 필터 vs 허가한다 우선순위가 무엇일까??
    OncePerRequest의 승입니다.
    그러나 프로젝트에서는 OncePerRequest를 상속받은 필터를 거치지 않게 해야 했습니다.
.requestMatchers("/users/**").permitAll() 

/users/signup

  1. permitAll 이 아닌 Ignore 를 쓰려는데 적용이 되지 않았습니다.
    결정적인 차이는 permit은 영어의 의미대로 권한이 없지만 허용한다는 의미여서
    필터를 거치긴 합니다. 그러나 ignore은 필터를 무시하고 지나칩니다.

시도

방법1. shouldNotFilter

//    @Override   //아예 필터를 거치지 않게하는 방법 중 하나.
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        String excludePath = "/users";
        String path = request.getRequestURI();
        return path.startsWith(excludePath);
    }
public class JwtAuthorizationFilter extends OncePerRequestFilter

OncePerRequestFilter를 상속받는 클래스 내부에 shouldNotFilter를
오버라이드 하여서 특정 path를 포함한 요청은 필터를 거치지 않게 하는 방법을 썼습니다.
shouldNotFilter의 디폴트 값은 false입니다.


방법2. SecurityConfig 클래스에서 WebSecurityCustomizer 를 설정합니다.

@Bean
    public WebSecurityCustomizer webSecurityCustomizer(){
        return web -> {
            web.ignoring()
                    .requestMatchers("/users/**")
                    .requestMatchers(HttpMethod.GET, "/boards/**");
        };
    }

여기서 처음에 구글링 했을 때 antMatcher를 쓰던데 현재 버전에서는 적용이 안되는 것 같았습니다. 시큐리티 버전이 업데이트 되면서 보안의 문제가 있는 몇몇 메서드들이 deprecated 된 것 같습니다.


++

    @Bean
    public AuthExceptionFilter authExceptionFilter() {
        return new AuthExceptionFilter();
    }

    @Bean
    public JwtAuthorizationFilter jwtAuthorizationFilter() {
        JwtAuthorizationFilter jwtAuthorizationFilter = new JwtAuthorizationFilter(jwtUtil, userDetailsService);
        return jwtAuthorizationFilter;
    }
http.addFilterBefore(jwtAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore(authExceptionFilter(), JwtAuthorizationFilter.class);

처음엔 위 처럼 빈으로 주입받고 필터 관리에서 위처럼 작성해 주었으나 ignore가 먹히지 않았습니다.

bean으로 등록하면 커스텀 필터들이 Security Filter Chain 이 아닌 default filter chain에 포함되기 때문이라고 합니다.
따라서 Security Filter Chain에 포함되게끔 해주면 되는데 ...
Security Filter Chain 내부에 있는 코드를 변경해 주었습니다.

http.addFilterBefore(new JwtAuthorizationFilter(jwtUtil,userDetailsService), UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore(new AuthExceptionFilter(), JwtAuthorizationFilter.class);

bean을 해체하고 필터를 새로 생성해 주고 관리했더니 ignore가 잘 되었습니다.

사실 이 부분은 아직 공부가 더 필요한 것 같습니다.

해결

시도한 방법으로 요구사항을 구현할 수는 있었습니다.

알게된 점

ignore와 permit의 차이를 알 수 있었습니다.

permitAll은 권한이 없어도 스프링 시큐리티의 모든 필터를 통과시켜준다! 였습니다.
통과시켜준다는 말이 권한에 관련된 사항만 말하는 것입니다.
Ignore 은 아예 필터를 거치지 않는 것이고 permit은 거치긴 하되 스프링 시큐리티 관련 권한을 신경쓰지 않겠다는 것입니다. 그러니까 커스텀으로 추가한 로직은 적용이 안되는 것이었습니다.
자꾸 내가 만든 커스텀 필터를 통과하길래 permit이 그럼 무슨소용인가? 계속 의문이 들었는데 permit을 해주지 않으면 내가 만든 필터는 권한에 상관없이 통과하지만 결국 이후 필터에서 걸려서 403에러가 뜨는 것이었습니다.

그러나 대부분 permit을 쓰고 index등 정적리소스등이 필터를 거쳐야 하지 않을 때
ignore를 쓰는 것 같습니다.

다양한 필터들이 동작하고 있다는 사실과 그렇기 때문에 @Order() 를 써서 순서를 정해주면 필터들의 순서가 꼬여서 정상적으로 작동하지 않는다는 사실도 알게 되었습니다.

++위의 전체 과정을 통해서 security를 커스텀하는 방법이 있다는 정도는 알게 되었으나 실무에서 시큐리티를 이렇게 조작해서 쓰는지 궁금증이 생겼습니다.

profile
Slow but Steady

0개의 댓글