LoginSignup
5
2

More than 3 years have passed since last update.

【Rails】ajax使用時、「CSRF対策」を意識する。

Last updated at Posted at 2020-11-06

記事の内容

コメント機能(comment)をajaxを使って部分的に遷移させる方法で実装しました。更新機能を実装した際に、つまづいたところを残します。

開発環境

Ruby 2.7.2
Rails 6.0.3.4

内容

postに紐づく、コメント(comment)の内容(body)を更新する。
コントローラーは、このような感じです。

comment_controller.rb
class CommentsController < ApplicationController

  def update
    @comment = current_user.comments.find(params[:id])
    if @comment.update(comment_update_params)
      render json: @comment , status: :ok
    else
      render json: { comment: @comment, errors: { messages: @comment.errors.full_messages } }, status: :bad_request
    end
  end

  private

  def comment_update_params
    params.require(:comment).permit(:body)
  end
end

jsのコードはこのような感じです。

comment_edit.js
$(function() {
  // 一部抜粋

    $.ajax({
      type: 'PATCH',
      url: '/comments/' + commentId,
      data: {
        comment: {
          body: body
        },
      },
      dataType: 'json',
    }).done(function (data) {

      //成功処理

    }).fail(function () {

      //失敗処理

    });
  })
});

コメントの更新が成功すると、成功処理が行われます。
しかし、422エラーが発生したしまいました。Railsのログを確認すると以下のようになっていました。

Processing by CommentsController#update as JSON
  Parameters: {"comment"=>{"body"=>"あああ"}, "id"=>"36"}
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms | Allocations: 834)



ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

Can't verify CSRF token authenticity.と記載があります。
どうやら、CSRFトークンが付与されていなかったのが原因らしいです。

application.html.erbcsrf_meta_tagsを記載していました。

application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title> タイトル </title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

CSRFの対応策として記載するものらしいです。詳しくは↓Railsガイドをご確認ください。
Railsセキュリティガイド

これを踏まえ、CSRFトークンを付与する形で以下のようにコードを追加しました。

comment_edit.js
$(function() {
  // 一部抜粋

    $.ajax({
      type: 'PATCH',
      url: '/comments/' + commentId,
      data: {
        comment: {
          body: body
        },
      },
//追記ここから
        headers: {
          'X-CSRF-Token' : $('meta[name="csrf-token"]').attr('content')
        },
//追記ここまで
      dataType: 'json',
    }).done(function (data) {

      //成功処理

    }).fail(function () {

      //失敗処理

    });
  })
});

そしたら正常に動きました。

所感

PCは正直者です。指示されたものしか受け取りません(笑)

書き方は他にもあると思います。以下のRailsガイドを参考にしてみてもいいかもしれません。
Railsガイド Ajax CSRFトークン

5
2
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
5
2