프로그래밍/spring

SpringSecurity 적용 후 403 에러 발생! CSRF 그게 뭘까?

승민아 2024. 6. 18. 18:32

다음의 html을 작성했다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="/members/signup" method="post">
    <button type="submit">회원가입</button>
</form>

</body>
</html>

 

그냥 회원가입 버튼을 누르면 "/members/signup"으로 POST 요청을 보내는 html이다.

 

 

회원 가입 버튼을 눌러 POST 요청을 보냈더니 

403 에러 - 요청을 받았으나 권한 문제 발생

403 에러가 발생했다..

 

Security의 설정 빈을 다음과 같이 작성을 해서 분면 모든 요청을 허락했는데 말이다..

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        http.authorizeHttpRequests(request -> request
                .anyRequest().permitAll());

        return http.build();
    }

}

 

사실 스프링 시큐리티는 인증, 인가 외에도 다음 기능을 기본 지원했었다.

  • 인증
  • 인가
  • cors
  • csrf

적용된 CsrfFilter

 

여기서 403 에러가 발생한 원인은 csrf 필터 때문이였다.

 

CSRF ?

웹 보안 취약점중 하나로

Cross-Site Request Forgery로 "사이트 간 요청 위조"이다.

 

간단한 원리는 다음과 같다.

 

사용자가 네이버에 로그인을 통해 사용자 세션이 생성되고 소유합니다.

소유 도중에 사용자가 악성 스크립트 또는 사이트를 방문하여 사용자 세션을 공격자가 탈취, 이용한다.

 

예를 들어,

<img src="http://naver.com/logout"/>

위의 악성 스크립트 통해 사용자는 로그아웃을 당할 수 있다...!

 

 

방어 방법으로 CAPTHCA 등등 다양하지만

CSRF 토큰 방법을 알아보고 타임리프를 통해 쉽게 적용해보자!

 

CSRF 토큰 방법은 간단하다.

사용자는 사용자 세션에 값을 넣어 모든 요청시 해당 값을 포함하여 요청하며

서버는 해당 값을 검증 확인하여 방어하는 방법이다.

 

이것을 타임리프에서 "th:action"을 통해 쉽게 작성해준다.

<form th:action="@{/members/signup}" method="post">
    <button type="submit">회원가입</button>
</form>

 

"action" -> "th:action"으로 변경하고 403 에러는 발생하지 않는다.

 

렌더링된 html은 다음과 같다.

알아서 CSRF 토큰을 포함하여 요청시 함께 가도록 된다!

 

 

REST API 서버를 만든다면 CSRF 필터를 꺼버리면 그만이지만

이번에 만들고 있는 프로젝트는 토큰을 사용하지 않는 웹 사이트이다~ ㅎㅎ