[스프링 Security] CSRF 토큰 이야기 - csrf() 켰더니 로그아웃이 안 되네?

웹 개발/스프링 프레임워크

2021. 12. 14.

이슈? csrf.disable() 하지 않을 시 logout 동작하지 않음

[재현 과정]

  1. 시큐리티 설정> http.csrf.disable() 하지 않음> 즉 csrf 지원 활성화 함.
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/*").permitAll()
                .and()
                .authorizeRequests().antMatchers("/singers/**").authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/singers");
                //.and()
                //.csrf().disable();
    }
}
  1. /singers 페이지> 임의 뷰 클릭> /login 인터셉트된 화면> user / user 로 로그인> 주소창으로 /logout 수행
  2. https://user-images.githubusercontent.com/15683098/145700095-bc53718d-01da-4606-b91f-96f59da6d983.gif

 

이렇게 csrf 지원을 활성하니까 /logout이 동작하지 않는 모습입니다.

 

CSRF 토큰의 정의와 사용법 그리고 스프링 시큐리티의 CSRF 지원이란 무엇이며. 해당 옵션 활성시 /logout이 동작하지 않게 된 이유를 알아야 할 것 같습니다.

원인

LogoutConfigurer.java 코드를 보면 CSRF설정이 켜졌을 때 POST 리퀘스트로만 로그아웃 가능하게 되어있음.

https://user-images.githubusercontent.com/15683098/145703511-f24cdf43-e53b-40ec-a6ff-27ecc04dff5a.png

공식 문서에 따르면 [링크]

POST로만 기능을 제공한다면 CSRF 토큰이 반드시 요구되므로, 로그아웃 강제 공격을 방지할 수 있다는 점을 이유로 들고 있다.

 

100% ensure는 아니다. 로그아웃 요청을 트리거하는 DOM 이벤트를 자바스크립트로 생성할 수만 있다면 악의적으로 로그아웃을 유발할 수 있음. (XSS) 허나 POST로 로그아웃을 제공하는 것이 보안 향상에는 도움이 된다.

https://user-images.githubusercontent.com/15683098/145718292-258df007-f63d-42f1-a853-c0ca9663f8bf.png