๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Spring/Security

WebSecurity ignoring()์— ๋Œ€ํ•œ ์˜คํ•ด์™€ ๋ฏธ์ ์šฉ ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

by ํ‘์‹œ๋ฐ” 2023. 9. 10.

๐Ÿ˜ฌ ๋ฐฐ๊ฒฝ

ํšŒ์‚ฌ ํ”„๋กœ์ ํŠธ์—์„œ ํŠน์ • ์š”์ฒญ์„ ํ•„ํ„ฐ์—์„œ ์ œ์™ธํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์—ˆ๋‹ค. ํ•„์ž๋Š” ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ WebSecurity ignoring() ๋ฉ”์„œ๋“œ์— ํŠน์ • ํŒจํ„ด์ด ๋ณด์•ˆ(ํ•„ํ„ฐ๋ง)์— ๊ฑธ๋ฆฌ์ง€ ์•Š๋„๋ก ์ถ”๊ฐ€ํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด์ „์— ๋“ฑ๋กํ•œ ํ•„ํ„ฐ์— ๊ณ„์†ํ•ด์„œ ๊ฑธ๋ฆฌ๊ฒŒ ๋˜์—ˆ๊ณ , ๊ด€๋ จ ์›์ธ์„ ํŒŒ์•…ํ•˜๊ณ  ํ•ด๋‹น ์ผ€์ด์Šค๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ• ์ง€ ๊ณ ๋ฏผํ•œ ๋‚ด์šฉ์— ๋Œ€ํ•ด์„œ ์ž‘์„ฑํ•ด ๋ณธ๋‹ค.

WebSecurity ignoring() ๊ธฐ๋Šฅ์ด๋ž€?

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์—์„œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ตฌ์„ฑํ•œ ๋ณด์•ˆ์  ์š”์†Œ(ํ•„ํ„ฐ, ํŒจํ„ด, ๊ถŒํ•œ ๋“ฑ)๋ฅผ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋„๋ก WebSecurity์˜ ignoring() ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

 

ํ•ด๋‹น ๊ธฐ๋Šฅ์— ๋“ฑ๋ก๋œ ํŒจํ„ด๋“ค์€ ๋ณด์•ˆ์  ์š”์†Œ๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ํ†ต๊ณผํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์ธ์ฆ/์ธ๊ฐ€๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์€ ์ •์  ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์š”์ฒญ์€ ํ•ด๋‹น ๊ธฐ๋Šฅ ํ™œ์šฉํ•œ๋‹ค. (๋™์  ๋ฆฌ์†Œ์Šค ์š”์ฒญ์€ ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์—์„œ permitAll()์„ ๊ถŒ์žฅํ•œ๋‹ค.)

- SecurityConfig

@Configuration
@RequiredArgsConstructor
public class SecurityConfig{

    private final ShibaHolicFilter shibaHolicFilter;

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().antMatchers("/shibaHolic");
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.addFilterBefore(shibaHolicFilter, UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .anyRequest()
                .authenticated();
        return http.build();
    }
}

- Controller

@RestController
public class ShibaHolicController {

    @GetMapping("/shibaHolic")
    public String getShibaHolic() {
        return "ํ‘์‹œ๋ฐ”";
    }
}

- Filter

@Component
public class ShibaHolicFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        System.out.println("ํ•„ํ„ฐ ๊ฑธ๋ฆผ");
        filterChain.doFilter(request, response);
    }
}

 

SecurityConfig์— ShibaHolicFilter๋ฅผ ๋“ฑ๋กํ•˜๊ณ , ๋‹ค๋ฅธ ์š”์ฒญ์— ๋Œ€ํ•ด์„œ๋Š” ๋ฐ˜๋“œ์‹œ ์ธ์ฆํ•˜๋„๋ก ์„ค์ •ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  WebSecurity ignoring() ํŒจํ„ด์—๋Š” /shibaHolic์„ ๋“ฑ๋กํ•œ๋‹ค.

 

์ด๋ ‡๊ฒŒ ์„ค์ •ํ•˜๊ณ  GET ๋ฉ”์„œ๋“œ๋กœ /shibaHolic์„ ํ˜ธ์ถœํ•˜๋ฉด,

์ธ์ฆ ์—†์ด ํ†ต๊ณผ๋˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ, ์ด๋ฏธ์ง€์™€ ๊ฐ™์ด ShibaHolic ํ•„ํ„ฐ๋ฅผ ๊ฑฐ์ณ์„œ ๋„˜์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ”Ž ์›์ธ

์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ํ•„ํ„ฐ์—๋Š” ๊ฑธ๋ฆฌ์ง€ ์•Š์•˜์ง€๋งŒ, ๋ฌธ์ œ๋Š” ServletFilter์—์„œ ๊ฑธ๋ฆฐ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

์Šคํ”„๋ง ๊ณต์‹๋ฌธ์„œ์—๋Š” "Bean์œผ๋กœ ๋“ฑ๋ก๋œ ํ•„ํ„ฐ๋Š” ์ž๋™์œผ๋กœ ServletFilterChain์— ๋“ฑ๋ก๋œ๋‹ค"๋ผ๊ณ  ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ Filter๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•˜๋ฉด์„œ ์ž๋™์œผ๋กœ ServletFilterChain์— ํ•„ํ„ฐ๊ฐ€ ๋“ฑ๋ก๋˜๊ณ ,

SecurityFilterChain์—๋Š” addFilterBefore() ๋ฉ”์„œ๋“œ๋กœ ์ธํ•ด ํ•„ํ„ฐ๊ฐ€ ๋˜ ๋“ฑ๋ก๋˜๋ฉด์„œ ์ด 2๋ฒˆ ๋“ฑ๋ก๋œ๋‹ค.

 

ApplicationFilterChain์„ ๋””๋ฒ„๊น…ํ•˜๋ฉด ์ด๋ฏธ์ง€์˜ 3, 4์™€ ๊ฐ™์ด, SecurityFilterChain๊ณผ ShibaHolicFilter ๋‘˜ ๋‹ค ๋“ฑ๋ก๋˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“• ํ•ด๊ฒฐ

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์ด ์žˆ์œผ๋ฏ€๋กœ, ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋งž๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

1. ํ•„ํ„ฐ๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•˜์ง€ ์•Š๋Š”๋‹ค.

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค. ํ•„ํ„ฐ๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•˜์ง€ ์•Š๊ณ  Security ์„ค์ •์— ์ƒ์„ฑ์ž๋กœ ๋“ฑ๋กํ•œ๋‹ค๋ฉด, ํ•„ํ„ฐ๊ฐ€ 2๊ฐœ ๋“ฑ๋ก๋˜๋Š” ์ผ์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•„์ž๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ์˜์กด์„ฑ ์ฃผ์ž…์ด ํ•„์š” ์—†๋Š” ๋‹จ์ˆœํ•œ ํ•„ํ„ฐ๋ผ๋ฉด ํ•ด๋‹น ๋ฐฉ๋ฒ•์„ ์ถ”์ฒœํ•œ๋‹ค.

- SecurityConfig

@Configuration
@RequiredArgsConstructor
public class SecurityConfig {

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().antMatchers("/shibaHolic");
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.addFilterBefore(new ShibaHolicFilter(), UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .anyRequest()
                .authenticated();
        return http.build();
    }
}

- Filter

public class ShibaHolicFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        System.out.println("ํ•„ํ„ฐ ๊ฑธ๋ฆผ");
        filterChain.doFilter(request, response);
    }
}

 

ShibaHolicFilter๋ฅผ ์˜์กด์„ฑ ์ฃผ์ž…๋ฐ›์ง€ ์•Š๊ณ , ์ธ์Šคํ„ด์Šคํ™”ํ•ด์„œ ๋“ฑ๋กํ•œ๋‹ค.

์ด๋Ÿฌ๋ฉด Bean์œผ๋กœ ๋“ฑ๋ก๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, Servlet Filter์— ์ถ”๊ฐ€๋  ์ผ์ด ์—†๋‹ค.

 

๋””๋ฒ„๊น…์„ ํ†ตํ•ด ํ™•์ธํ•ด ๋ณด๋ฉด ๋” ์ด์ƒ ShibaHolicFilter๊ฐ€ ๋“ฑ๋ก๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

2. ํ•„ํ„ฐ๋ฅผ Servlet Filter๋กœ ๋“ฑ๋ก๋˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.

์Šคํ”„๋ง์ด Bean์œผ๋กœ ๋“ฑ๋ก๋œ ํ•„ํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•˜๋Š” ์„ค์ •์„ ๋„๋ฉด, ํ•„ํ„ฐ๋ฅผ Bean์œผ๋กœ ๋“ฑ๋กํ•ด๋„ ๋”์ด์ƒ Servlet Filter๋กœ ๋“ฑ๋ก๋˜์ง€ ์•Š๋Š”๋‹ค.

@Configuration
public class WebConfig {

    @Bean
    public FilterRegistrationBean<ShibaHolicFilter> registration(ShibaHolicFilter filter) {
        FilterRegistrationBean<ShibaHolicFilter> registration = new FilterRegistrationBean<>(filter);
        registration.setEnabled(false);
        return registration;
    }
}

 

FilterRegistrationBean setEnabled ์˜ต์…˜์„ ๋„๋ฉด, ๋”์ด์ƒ Servlet Filter์— ํ•ด๋‹น ํ•„ํ„ฐ๊ฐ€ ์ถ”๊ฐ€๋˜์ง€ ์•Š๋Š”๋‹ค.

3. shouldNotFilter()๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํŠน์ • ํŒจํ„ด์—์„œ๋งŒ ํ•ด๋‹น ํ•„ํ„ฐ๊ฐ€ ์ ์šฉ๋˜๋„๋ก ์„ค์ •ํ•œ๋‹ค.

OncePerRequestFilter๋Š” shouldNotFilter()๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•˜์—ฌ ํŠน์ • ํŒจํ„ด์—๋งŒ ํ•„ํ„ฐ๋ฅผ ์ ์šฉ์‹œํ‚ค๊ฑฐ๋‚˜ ์ œ์™ธ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ํŠน์ • ํŒจํ„ด์˜ ๊ฒฝ์šฐ๋งŒ ํ•ด๋‹น ํ•„ํ„ฐ๋ฅผ ๊ฑฐ์น˜๊ฒŒ ํ•œ๋‹ค๋ฉด, ํ•„ํ„ฐ ๋“ฑ๋ก ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.

 

@Component
public class ShibaHolicFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        System.out.println("ํ•„ํ„ฐ ๊ฑธ๋ฆผ");
        filterChain.doFilter(request, response);
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        return !request.getServletPath().equals("/blackshiba") || !request.getMethod().equals("GET");
    }
}

 

GET ๋ฉ”์„œ๋“œ์— /blackshiba์œผ๋กœ ์˜ค๋Š” ๊ฒฝ์šฐ๋งŒ ํ•ด๋‹น ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ•˜๋„๋ก ํ•˜๋ฉด์„œ, /shibaHolic์ธ ๊ฒฝ์šฐ ํ•ด๋‹น ํ•„ํ„ฐ๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๋„๋ก ํ•˜์˜€๋‹ค.

๋Œ“๊ธ€