Rails/React 앱에서 ActionController::InvalidAuthenticityToken 오류 해결

Rails(백엔드) 및 React(프론트엔드) 애플리케이션 구축을 막 시작했습니다. Webpack을 구성했습니다. 데이터베이스를 설정했습니다. 백엔드와 프런트엔드를 연결했습니다.

첫 번째 모델, 컨트롤러 및 뷰를 구축했습니다. 첫 번째 POST 요청을 테스트하러 가면 발생합니다...

ActionController::InvalidAuthenticityToken


및/또는

Can't verify CSRF token authenticity.


너 구글. 당신은 운다. 당신은 진심으로 rack-cors를 사용하려고 합니다.

절대 두려워하지 마! 간단한 해결책은 다음과 같습니다.

1. application.html.erb를 기록해 둡니다.



먼저/app/views/layouts/application.html.erb를 엽니다. 이 보기는 $rails new 명령을 실행할 때 생성되었어야 합니다.

다음 태그가 표시되어야 합니다. <%= csrf_meta_tags %>
도대체 이것들이 뭐야? Ruby docs에서:

These are used to generate the dynamic forms that implement non-remote links with :method.

For AJAX requests other than GETs, extract the “csrf-token” from the meta-tag and send as the “X-CSRF-Token” HTTP header.



2. 관련 구성 요소에서 CSRF 토큰을 가져옵니다.



나에게 문제가 되는 컨트롤러 작업은 user#create였으며, 이는 관련 '보기' 구성 요소가 내 가입 양식임을 의미합니다.

토큰을 캡처하기 위해 구성 요소에 JavaScript 라인을 추가했습니다.
/app/javascript/components/Signup.jsx

const token = document.querySelector('meta[name="csrf-token"]').content;


여기서 우리는 DOM을 쿼리하고 이름 값이 "csrf-token"인 메타 태그를 찾고 변수 토큰에 할당합니다.

제출 시 토큰 전달



그런 다음 새 변수를 내 가입 함수(상위 구성 요소에서 소품으로 전달됨)에 전달하여 가입 작업에서 액세스할 수 있도록 했습니다.

/app/javascript/components/Signup.jsx

const handleOnSubmit = (e) => {
    e.preventDefault()
    signup({username, email, password}, token)
}


토큰을 수락하도록 가입 작업을 변경하지 않았으므로 아직 작동하지 않습니다.

귀하의 행동에서 토큰을 수락하십시오



내 userActions로 돌아가서 등록 작업을 약간 조정합니다.
/app/javascript/actions/userActions.js

export const signup = (credentials, token) => {
    return dispatch => {
        return fetch('http://localhost:3000/signup', {
            credentials: 'include',
            method: "POST",
            headers: {
                "X-CSRF-Token": token,
              "Content-Type": "application/json"
            },
            body: JSON.stringify(credentials)
          })
        .then(response => response.text())
        .then(userData => {
            if(userData.error){
                console.log(userData.errors)
            } else {
                dispatch(addUser(userData.data))
            }

        })
        .catch(console.log())
    }
}


먼저 두 번째 매개 변수인 토큰을 수락하도록 signup()을 변경합니다.export const signup = (credentials, token) => {
그런 다음 헤더 아래에 토큰을 전달합니다.

            headers: {
                "X-CSRF-Token": token,
              "Content-Type": "application/json"
            },


그리고 그게 다야! 이제 백엔드에 대한 POST 요청을 성공적으로 완료할 수 있습니다.



요약하자면:
  • JS를 사용하여 POST가 발생하는 구성 요소에서 application.html.erb에 의해 출력된 토큰을 캡처합니다.
    /app/javascript/components/Signup.jsx

  • const token = document.querySelector('meta[name="csrf-token"]').content;
    


  • 제출 시 POST 작업에 토큰을 보냅니다.
    /app/javascript/components/Signup.jsx

  • const handleOnSubmit = (e) => {
        e.preventDefault()
        signup({username, email, password}, token)
    }
    


  • POST 작업에서 백엔드로 토큰을 보냅니다.
    /app/javascript/actions/userActions.js

  • export const signup = (credentials, token) => {
        return dispatch => {
            return fetch('http://localhost:3000/signup', {
                credentials: 'include',
                method: "POST",
                headers: {
                    "X-CSRF-Token": token,
                  "Content-Type": "application/json"
                },
                body: JSON.stringify(credentials)
              })
           ....
        }
    }
    

    좋은 웹페이지 즐겨찾기