PlayGround/마실가실 리팩토링

[1년 후 마실가실] Spring Security 특정 url 제외

HJ0216 2024. 9. 18. 07:37

1년 전 진행했던 마실가실 프로젝트를 🛠️리팩토링하며 정리한 내용입니다.

 

사소한 생각으로부터 시작된 Filter Chain 수정 이야기..

 

필터로 Validate를 하니, 모든 url에 대해 Filter가 적용이 되어 너무 비효율적이지 않은가에 대한 해답을 들고 왔습니다.

 

JwtAuthentificationFilter와 함께할 합격의 목걸이를 받을 url 설정 기록 입니다..

 

 

 

관련된 글

https://hj0216.tistory.com/947

 

[1년 후 마실가실] JWT와 로그아웃(3) 로그아웃

1년 전 진행했던 마실가실 프로젝트를 🛠️리팩토링하며 정리한 내용입니다.  스마트 루피를 데려온 이유는 스마트하게 로그아웃을 완성했기 때문입니다. JWT와 로그아웃(1) 게시물을 8월 23일

hj0216.tistory.com

 

 

JwtAuthentificationFilter.java
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.httpBasic(AbstractHttpConfigurer::disable)
            .csrf(AbstractHttpConfigurer::disable)
            .cors(httpSecurityCorsConfigurer -> corsConfigurationSource())
            .sessionManagement(sessionManagement ->
                    sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )                .authorizeRequests((auth) -> auth
                            .requestMatchers("/api/v2/users/login").permitAll()
                            .requestMatchers("/api/v2/users/me", "/api/v2/users/logout").hasRole("USER")
            )
            .addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);

    return http.build();
}

🚨문제: JwtAuthentificationFilter에서 Access Token의 유효성 검증을 수행하는데, 유효성 검증이 필요없는 회원가입이나 Access Token 재발행에서도 Filter가 동작

 

🤓 해결 방안: 특정 url에서만 filter가 동작하도록 수정

 

🛠️해결1

shouldNotFilter
public JwtAuthenticationFilter jwtAuthenticationFilterForSpecificUrls() {
    return new JwtAuthenticationFilter(jwtTokenProvider) {
        @Override
        protected boolean shouldNotFilter(HttpServletRequest request) {
            String path = request.getServletPath();
            return !("/api/v2/users/login".equals(path) || "/api/v2/users/me".equals(path) || "/api/v2/users/logout".equals(path));
        }
    };
}

public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.httpBasic(AbstractHttpConfigurer::disable) // 기본 HTTP 인증을 비활성화
            .csrf(AbstractHttpConfigurer::disable) // CSRF 보호를 비활성화, CSRF 토큰을 사용하여, 클라이언트가 서버에 요청할 때마다 유효한 토큰을 함께 전송해야만 요청이 성공하도록 하는 방식으로 보안을 강화 -> 토큰으로 대체
            .cors(httpSecurityCorsConfigurer -> corsConfigurationSource())
            .sessionManagement(sessionManagement ->
                    sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 세션을 사용하지 않고, 상태를 저장하지 않도록 설정(STATLESS)
            ).authorizeHttpRequests(auth -> auth
                    .requestMatchers("/api/v2/users/login").permitAll()
                    .requestMatchers("/api/v2/users/me", "/api/v2/users/logout").hasRole("USER")
            )
            .addFilterBefore(jwtAuthenticationFilterForSpecificUrls(), UsernamePasswordAuthenticationFilter.class);

    return http.build();
}

 

🛠️해결2

WebSecurityCustomizer
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
    return (web) -> web.ignoring()
            .requestMatchers("/api/v2/users/new", "/api/v2/users/reissue");
}

 

⭐ 차이점

* shouldNotFilter : 특정 경로에 대한 특정 필터만 제외

* WebSecurityCustomizer: 경로에 대해 모든 필터 체인을 비활성화

 

 

 

🙋‍♀️

본 포스트는 공부 목적으로 작성하였습니다.
보시는 도중 잘못된 부분이나 개선할 부분이 있다면 댓글로 알려주시면 수정하도록 하겠습니다.

 

📑

참고 자료