Languages/Ruby or Rails2008.08.01 13:36

이 문제는 나그네 님께서 지적해주신 문제입니다. 최신 버전의 Rails는 일반 html 파일에 포함된 form의 input 필드들과 연동할때, 약간의 문제가 있습니다.

가령 Beginning Ruby on rails의 5장에 수록된 예제처럼 input.html 파일을 다음과 같이 만들었다고 해 봅시다.

<html>
<body>
    <form action="/look/at">
    <input type="text" name="text1"/>
    <input type="submit"/>
    </form>
</body>
</html>

이 form에 뭔가를 입력하고 submit 버튼을 누르면 /look/at 액션이 실행될 것이고, 그 결과가 화면에 출력될 것입니다. 그런데 그냥 이렇게만 하면 별 문제가 없다가, 위의 html 코드를 다음과 같이 바꾸면 문제가 발생합니다.

<html>
<body>
    <form action="/look/at" method="post">
    <input type="text" name="text1"/>
    <input type="submit"/>
    </form>
</body>
</html>

위와 같이 바꿔놓고 submit  버튼을 눌러보면, 다음과 같은 오류가 발생하는 것을 볼 수 있습니다.

ActionController::InvalidAuthenticityToken in LookController#at

액션 컨트롤러 쪽에서 AuthenticityToken이라는 것을 요구하는데 그게 없기 때문에 발생하는 오류입니다. 이 문제를 좀 더 정확하게 이해하기 위해, 다음과 같이 해 봅시다. 일단 controller Look에 input이라는 액션을 추가합니다.

class LookController < ApplicationController
    def at
        @data = params[:text1]
    end

    def input
    end

end

그런 다음 위의 html 코드를 다음과 같이 바꾸고, app/views/look 아래에 input.html.erb 라는 이름으로 복사해 넣습니다.

<html>
<body>
    <% form_tag '/look/at', :method=>:post do %>
    <input type="text" name="text1"/>
    <input type="submit"/>
    <% end %>
</body>
</html>

그런 다음에, 브라우저로 /look/input을 엽니다. 그리고 나서 브라우저의 소스 코드 보기 기능을 통해 소스 코드를 봅시다. 다음과 같이 되어 있는 것을 볼 수 있습니다.

<html>
<body>
 <form action="/look/at" method="post"><div style="margin:0;padding:0"><input name="authenticity_token" type="hidden" value="8f846ee3232eda791b4bf4c9d6d0a20478afcf8a" /></div>
 <input type="text" name="text1"/>
 <input type="submit"/>
 </form>
</body>
</html>

결국, /look/at은 method가 post일때 위의 token이 오기를 기대하는데 안오니까 불평을 해 댔던 것이죠. 이 문제를 해결하는 방법은 두가지가 있는데, 위에서처럼 모든 form 태그를 전부 form_tag 메소드를 써서 생성하는 것입니다. 그러면 알아서 넣어주니까 괜찮죠.

하지만 <div> 태그가 원래 원칙적으로 line break를 유발하는 습성이 있기 때문에, 웹 디자이너에게는 솔직히 짜증나는 부분이 될 수 있습니다. 그냥 hidden input filed로 두면 되었을텐데 div는 뭐하러 두었는지 참 ㅋㅋ

가장 간단한 해결책은 CSRF(Cross-Site Request Forgery) 공격을 막기 위해 도입된 위 feature를 강제로 동작하지 않도록 만드는 것입니다.

위의 경우라면, 컨트롤러 Look에 다음의 한줄을 넣어주세요.

skip_before_filter :verify_authenticity_token

제가 Beginning Ruby on Rails를 번역하면서 원저자가 책을 썼던 시점에 비해 바뀐 부분을 반영해 넣느라 고민을 좀 했었는데, 이렇게 책을 내놓고 보니 또 그 와중에 뭔가 새로운 기능이 계속 추가가 되어서 -_-;;

어쨌던 불편을 끼쳐드려서 죄송합니다. 앞으로도 이런 부분을 발견할 때 마다, 그리고 독자 분들의 질문이 있을 때 마다 가능한한 열심히 답변을 드리도록 하겠습니다.


신고
Posted by 이병준

소중한 의견, 감사합니다. ^^

  1. 전 원인도 모르고 그냥 첫번째 방법 썼는데 ^^ 좋은 정보 감사합니다~

    2008.08.01 14:26 신고 [ ADDR : EDIT/ DEL : REPLY ]