Computer Engineering/ruby on rails

[ruby on rails] err 422 및 CSRF token authenticity 해결

soohey 2022. 6. 24. 12:06

Error

Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 3ms 

 

문제 상황

ajax를 이용해서 data update를 하려고 할 때 422에러와 함께 csrf token 에러가 발생했습니다.

 

문제 원인

1.  422

  • 422에러는 서버가 요청을 이해했고 요청 문법도 올바르지만 요청된 지시를 따를 수 없음을 의미합니다.
  • 그러므로 클라이언트는 요청을 수정해야할 필요가 있습니다! (err422는 동일한 형태로 다시 보내서는 안됨을 의미함)

2. CSRF token authenticity

  • Can't verify CSRF token authenticity. 는 레일즈에서 제공하는 form태그로 method 요청시 문제가 없는데, javascript로 요청시 발생할 수 있습니다.
  • CSRF는 사용자가 자신의 의지와 상관없이 특정 웹페이지를 보안에 취약하게 하는 공격입니다.
  • rails에서는 CSRF 토큰을 생성한 뒤, 서버에 request시 해당 토큰을 포함시켜 세션에 저장된 값과 request parameter에 담긴 토큰값을 비교하여 같을 때만 사용자가 요청했다고 판단하여 이를 방지합니다.

CSRF 토큰은 application.html.erb에 심어져 있습니다.

<%= csrf_meta_tags %>

위 코드는 html에서 아래처럼 보입니다.

<meta name="csrf-param" content="">
<meta name="csrf-token" content="">

javascript에서는 데이터를 전송할 때 토큰을 읽은 후 토큰과 함께 요청을 보내야 합니다.

token = $('meta[name="csrf-token"]').attr('content');

https://velog.io/@ayokinya/Rails-6%EC%97%90%EC%84%9C-CSRF-%EB%8C%80%EC%9D%91%EC%B1%85

 

Rails 6에서 CSRF 대응책

Rails 6에서 제공하는 form으로 POST 요청을 하면 문제가 없는데,javascript로 POST를 실행하면 can't verify CSRF token authenticity 문구가 뜨면서 데이터 생성이 안 됐다. 이 문제를 해결하기 위해 검색을 하다

velog.io

 

해결

method를 post -> patch로 수정합니다. (위 에러와는 상관없음)

또한 토큰 에러를 해결하기 위해 헤더를 추가해줍시다!

 

코드 예시

// view

$.ajax({
        headers: {
          'Content-Type': "application/json",
          'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        },
        dataType: "json",
        cache: false,
        type: "patch",
        url: url,
        data: JSON.stringify(requestBody)
      }).done(function (data){

        alert(data.status)

      })