【Rails】Strong Parameterの使い方と仕組みを徹底解説【初心者向け】

Strong Parameterの使い方と仕組みを徹底解説Ruby on Rails

この記事では、RailsにおけるStrong Parameterの使い方や注意点について初心者向けに解説します。
Strong ParameterはRails4で導入され、現在は必須の技術です。
本記事では、Strong Parameterの使い方や注意点について詳しく解説します。

スポンサーリンク

Strong Parameterとは何か?

Strong Parameterはモデルに保存されるパラメータを許可されたもの以外は処理しないように設定します。フォームから送信される外部からの入力値を直接モデルに保存することを禁止して、悪意のあるユーザーによる不正なデータの送信やデータベースへの不正アクセスを防止します。

Strong Parameterはフォームから送信されるデータを受け取り、許可リストに含まれるパラメータ以外は捨てて、外部からの入力値に対する攻撃を防止できます。Strong Parameterによりアプリケーションの安全性を高められます。

Strong Parameterが導入された理由

Strong ParameterはMassAssignment脆弱性を回避するために非常に重要な機能です。MassAssignment脆弱性は外部からの入力値を直接モデルに保存する場合に、不正なデータが保存される可能性がある脆弱性です。Strong Parameterを使用すると許可されたパラメータ以外は保存できないようにできるのでMassAssignment脆弱性を回避できます。

Strong Parameterが導入される前のRailsでのデータ保存

Strong Parameterが導入される以前は以下のようにパラメータをそのまま使ってデータ保存できました。

def update_profile
  user = User.find(params[:id])
  user.update(params[:user])
end

なぜならRailsの規約に従うとparamsは以下のようなハッシュ形式になっているためです。

{
  ...
  "id" => "1",
  "user" => {
      "name" => "山田太郎",
      "profile" => "サラリーマン"
   }
   ...
}

上記の例では params[:user] とすると以下のようになります。

   {
      "name" => "山田太郎",
      "profile" => "サラリーマン"
   }

これを User.update に渡すと、nameカラムとprofileカラムにそのまま保存できるという仕組みになっています。

MassAssignment脆弱性の具体例

悪意を持ったユーザが開発者の意図していないパラメータを追加して送ってきたとします。

上記のパラメータに password パラメータを追加しました。

{
  ...
  "id" => "1",
  "user" => {
      "name" => "山田太郎",
      "profile" => "サラリーマン"
      "password" => "password"
   }
   ...
}

上記の例では params[:user] とすると以下のようになります。

   {
      "name" => "山田太郎",
      "profile" => "サラリーマン"
      "password" => "password"
   }

ここでusersテーブルにはpasswordカラムが存在し、開発者は公開するつもりがなかったとします。

User.update(params[:user])のように渡し、上記のようなパラメータが送られてきた場合、意図せず passwordカラムは更新されてしまいます。

Strong ParameterでMassAssignment脆弱性を回避

以下はStrong Parameterの使用例です。

class UsersController < ApplicationController
  def update_profile
    user = User.find(params[:id])
    user.update(user_params)  # Strong Parameterを使うように変更
  end

  private

  def user_params
    params.require(:user).permit(:name, :profile)
  end
end

上記の例では、 user_params メソッドによって、paramsハッシュから user キーに対応する値のうち、nameprofileのみを許可しています。許可していないパラメータはデータベースには保存されないのでMassAssignment脆弱性を回避できます。

Strong Parameterの使用方法

Strong Parameterの設定

Strong Parameterを使用するためには、コントローラーにて定義する必要があります。Strong Parameterは許可するパラメーターを指定し、指定されたパラメーター以外は取り扱わないようにします。

例えば、ブログ記事の投稿フォームで、タイトルと本文のみを許可する場合は、以下のようにStrong Parameterを使用して定義します。

def post_params
  params.require(:post).permit(:title, :body)
end

Strong Parameterの使用

Strong Parameterを定義した後は、コントローラー内で許可されたパラメーターを使用します。

例えば上記で定義したStrong Parameterは以下のように使用します。

def create
  @post = Post.new(post_params) # 定義したメソッドを使用
  if @post.save
    redirect_to @post
  else
    render 'new'
  end
end

許可していないパラメータの扱いを決める設定

許可されていない値が送られてきた場合、設定値によって動作が変わります。

設定値は config/environments/development.rb (production環境の場合は config/environments/development.rb) に以下を追加します。

config.action_controller.action_on_unpermitted_parameters = 設定値

設定値は以下のようになっています。

設定値説明デフォルト値
:raise許可されていないパラメータを保存しようとすると例外を発生する
:log許可されていないパラメータを保存しようとするとログだけ残して無視するtest, devepment 環境のときのデフォルト値
false何もしないproduction環境のときのデフォルト値

test, development 環境のときはデフォルト値は:log, それ以外はfalseとなっています。

:raiseを指定して許可していないパラメータを保存しようとすると以下のようなエラーとなります。

:logを指定した時はログファイルに以下のようなログが残り、許可していないパラメータを無視した上で保存処理自体は通過します。

Unpermitted parameter: :password

falseを指定したときは、例外もログも出ず、許可していないパラメータを無視した上で保存処理が通過します。

Strong Parametersの仕組み

Strong Parameterを使用するには、require/permitメソッドを使用します。

require/permit メソッドを使って何が起きているのかを確認するには binding.pry を使用するとよいでしょう。

def post_params
  binding.pry
  params.require(:post).permit(:title, :body)
end

binding.pryの使い方については以下を参照してください。
【Rails】pry-byebug(binding.pry)で効率よくデバッグ!インストールから使い方・Tipsまで

Strong Parameterのrequireメソッドは、指定されたキーが含まれていることを確認し、キーの値を許可します。

Strong Parametersのpermitメソッドは、指定されたパラメータのみを許可し、それ以外をフィルタリングするために使用されます。

例えば上記の例では params は以下のようなハッシュとになっています。

[1] > params
=> #<ActionController::Parameters {
    ...
    "post"=>{"title"=>"タイトル", "body"=>"本文"},
    ...
  }
  permitted: false>

permitted: false はnewやupdateなどのメソッドに渡しても、このままでは保存させない、ということを表します。

"post"=>{"title"=>"タイトル", "body"=>"本文"} を保存したいのでrequireでpostだけにしぼります。

[2] > params.require(:post)
=> #<ActionController::Parameters {"title"=>"タイトル", "body"=>"本文"}
  permitted: false>

"post"=>{"title"=>"タイトル", "body"=>"本文"}{"title"=>"タイトル", "body"=>"本文"}だけに絞れました。ただし permitted: false なのでまだ保存はできません。

permit メソッドを使ってtitle, body カラムだけ保存できるようにします。

[3] params.require(:post).permit(:title, :body)
=> #<ActionController::Parameters "title"=>"タイトル", "body"=>"本文"
  permitted: true>

permitted: true となり、 "title"=>"タイトル", "body"=>"本文” だけ保存できるオブジェクトを作成できました。これで以下のようにモデルのnewやcreate, update などのメソッドに直接渡すと保存できます。

post = Post.new(params.require(:post).permit(:title, :body))
post.save

コントローラの中で何度も使うので private メソッドとするのが一般的です。

def create
  post = Post.new(post_params)
  post.save
  ...
end

private

def post_params
  params.require(:post).permit(:title, :body)
end

まとめ

Strong Parameterについて解説しました。

Strong Parameterは、Railsでのセキュリティを確保するために非常に重要な機能です。

フォームから送られてきたパラメータを使ってモデル経由でデータベースに保存する場合は必ず使用します。
外部からの不正なデータ送信やデータベースへの不正アクセスを防止します。

Railsを使用した開発では必須すきるですのでぜひマスターしてください。

タイトルとURLをコピーしました