8
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Rails]aタグでも「data-method="delete"」を設定すればlink_toと同じ挙動

Posted at

#概要
railsにおいてCSRF対策の学習中、ヘルパーを使わないとエラーになるとのことで、試しにクロームでlink_toのフォームの検証をしてaタグでdeleteを記述したところ、エラーにならなかったので、いろいろと調べて見ました。

結論は、CSRF対策の本質はlink_toではなく、カスタムデータ属性にありました、ということです。

#問題提起

<%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %>

上記をクロームで検証したところ、

<a rel="nofollow" data-method="delete" href="/tweets/10">削除</a>

となっていました。

CSRF対策ではlink_toとヘルパーをつかうとトークンが発行されて、問題のないリクエストかを判断するとのことでしたので、このaタグに書き換えたらトークンは発行されないのでは? と思い、実際にファイルを書き換えたところ・・・・・。

結局、トークンが発行され、link_toとなにも変わりませんでした。

aタグでもいけるじゃん!
と思ったのが今回いろいろ調べたきっかけです。

※冷静に考えると、クロームでの検証が本物で、ファイルを書き換えて検証結果と同じにすることに意味はなかったのですが、そこのツッコミはご容赦いただきたいです。

#発見した記事

最初に発見した記事です。
link_toで突然methodが効かなくなって困ってるあなたへ

ここからmethodにjQueryが関わっているらしいことがわかりました。
そういえば、aタグにカスタムデータ属性が設定されています。

この辺に、link_toのカラクリがありそうです。

#rails.js

// Handles "data-method" on links such as: |
// <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a> 
    handleMethod: function(link) { 
      var href = rails.href(link), 
         method = link.data('method'), 
         target = link.attr('target'), 
         csrfToken = rails.csrfToken(), 
         csrfParam = rails.csrfParam(), 
         form = $('<form method="post" action="' + href + '"></form>'), 
         metadataInput = '<input name="_method" value="' + method + '" type="hidden" />'; 

       if (csrfParam !== undefined && csrfToken !== undefined && !rails.isCrossDomain(href)) { 
        metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />'; 
      } 

       if (target) { form.attr('target', target); } 
  
      form.hide().append(metadataInput).appendTo('body'); 
       form.submit(); 
     }, 

jquery-ujsのgithubからです。
https://github.com/rails/jquery-ujs/blob/master/src/rails.js

ここからカスタムデータ属性の値を取得してメソッドを決定、またトークンをくっつけていることがわかります。

また、ブラウザがDELETEのHTTPメソッドをサポートしていないことから、

<input type="hidden" name="method" value="delete">

としてform タグから _method を指定してdeleteメソッドを再現していることもわかります。

#まとめ
まだしっかり理解したわけではないのですが、アプリケーション外からのリクエストだとこのrails.jsを通さないのでCSRFを防げるということなのでしょうか。

補足、訂正がありましたら、教えていただけると幸いです!

以下、参考記事。
https://cre8cre8.com/rails/get-post-delete-put-match-routes.rb.htm
https://spitfire-tree.hatenadiary.org/entry/20120323/1332477590

8
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?