ガラシのパルプンテ頼み

地方産限界エンジニアのグローバル独り言

【5分くらいでわかる】ストロングパラメータ is 何 | Rails入門

ストロングパラメータとは

strong parametersは、Action ControllerのパラメータをActive Modelの「マスアサインメント」で利用することを禁止します(許可されたパラメータは除く)。 したがって開発者は、マスアップデートを許可する属性をコントローラで明示的に指定しなければなりません。 strong parametersは、ユーザーがモデルの重要な属性を誤って更新してしまうことを防止するためのより優れたセキュリティ対策です。

引用:Action Controller の概要 - Railsガイド

マスアサインメントとは

RailsにおけるDBの更新処理形で、複数のカラムを一括で指定することが可能です。 フォームから送られてきたパラメーターをひとつにまとめて、一度に保存できます。

User.create(name: 'garasi', age: 28, admin: true)

マスアサインメントの脆弱性

マスアサインメントはフォームから入力された複数の項目をキーバリューとして受け取って、モデル側でそれらをまとめて更新できる便利な機能である反面、 開発者側がなんの考慮もせずにフォームからの情報をマスアサインメントでモデルに渡してしまうと、悪意のあるパラメータを受け付けてしまう可能性があります。

例えばUserモデルにadminという管理者権限の有無を示すフラグが設けられており、アプリの開発者や管理者のみtrueにして、管理者用の画面へのアクセスを許可していたとしましょう。 もし悪意のある第三者がユーザー登録時に、Chromeのdevツールなどを用いてパラメータにadmin: true を付与してリクエストを送信してきた場合、 悪意のある第三者に管理者権限を持ったアカウントが発行されてしまい、アプリケーションが危険に晒されてしまう危険性があります。

改めてストロングパラメータとは

フォームから渡ってきたパラメータにコントローラー側であらかじめ許可する項目を指定して、 フォーム上から悪意のあるパラメータが送られてきた場合に開発者側で許可したカラム以外の更新を防ぐことを可能にしたもの。 要するに安全が保証されたパラメータをマスアサインメントでモデルに渡すためのRailsのセキュリティ機構と言えるでしょう。

具体的な使い方

一次元構造のハッシュ、二次元構造のハッシュでそれぞれ以下のように定義する必要があります

#一次元ハッシュの場合
params.permit(:キー名)

# 二次元ハッシュの場合
params.require(:モデル名).permit(:キー名)

パラメータを受け取るコントローラーのprivateメソッドとして定義することが多いです

 def create
    user = User.new(user_params) # =>{ name: "garasi", age: 28 }と同義
    if user.save
        redirect_to root_path, notice: '登録が完了しました'
    else
        render :new
    end
 end

 private
 # 例:名前と年齢以外を受け取らないため管理者権限など重要な項目を変更されることがない
 def user_params
  params.require(:user).permit(:name, :age)
 end

requireとpermit

コントローラー側で送られてきたパラメータを出力すると以下のようなハッシュが渡ってきていることがわかります。 以下の場合requireメソッドを使ってキーがuserの値のみを読み込み、その中で更にpermitメソッドにより許可する属性名を指定しています。

# Parameters
=> <ActionController::Parameters {
  "utf8"=>"", 
  "authenticity_token"=>"<token>", 
  "user"=>{"name"=>"garasi", "age"=>"29"}, 
  "commit"=>"送信", 
  "controller"=>"users", 
  "action"=>"create"
} permitted: false>

# controller
 def user_params
  params.require(:user).permit(:name, :age)
 end

これらを踏まえて再度ストロングパラメータの指定コードを見てみると以下のように読み取ることができます。 1. params.require(:user)ではparamsからキーがuserのバリューのみを受け取る 2. permit(:name, :age)をメソッドチェーンすることによってそのうちnameとageのカラムのみをモデルに受け渡すことを許可している

まとめ

  • モデルには複数の値を一括で受け取って更新できるマスアサインメントという更新処理系が存在する。
  • マスアサインメントには脆弱性があり、開発者がなにも考慮しないと悪意のある第三者に管理者権限を奪取されたり、アプリケーションのセキュリティ的に不都合な値を変更される可能性がある。
  • この脆弱性に対応するため、フォームからの受け取りを許可する項目をあらかじめ指定して安全な値のみをマスアサインメントでモデルに受け渡す必要がある。
  • この受け取る内容を制限したパラメータがストロングパラメータ。
  • ストロングパラメータはviewから送られてきたparamsにrequireメソッドとpermitメソッドで値を受け取るキーとバリューを指定することで作成できる。