【Rails】俺はストロングパラメーターを分かりたい

ストロングパラメータ is 何?

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

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

…hmm?

まずマスアサインメント is 何?

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

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

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

マスアサインメントはフォームから入力された複数の項目をキーバリューとして受け取って、
モデル側でそれらをまとめて更新できる便利な機能である反面、開発者側がなんの考慮もせずに
フォームからの情報をマスアサインメントでモデルに渡してしまうと、悪意のあるパラメータを受け付けてしまう。
例えば下記のように各Userにはadminという管理者権限の有無を示すフラグが設けられており、
アプリの開発者や管理責任者にのみこのフラグをtrueで付与して、管理者用の画面へのアクセスを許可していたとする。
もし悪意のある第三者がユーザー登録時にChromeのdevツールなどを用いて、パラメータにadmin: true を付与して
送りつけてきた場合、悪意のある第三者に管理者権限を持ったアカウントが発行されてしまいアプリケーションが
危険に晒されてしまう。

あらためてストロングパラメータ is 何?

フォームから渡ってきたパラメータ(params)にコントローラー側であらかじめ許可する項目を指定して(premit)、
フォーム上から悪意のあるパラメータが送られてきた場合に
開発者側で許可したカラム以外の更新を防ぐことを可能にしたもの。要するに安全が保証されたパラメータを
マスアサインメントでモデルに渡すための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 is 何?

コントローラー側で送られてきたparams(viewからフォームによって送られてきたデータ)を出力すると
以下のような二次元ハッシュが渡ってきていることがわかる。requireメソッドを使ってキーがuserの値のみを取り出している。

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

これらを踏まえて再度ストロングパラメータの指定コードを見てみると以下のように翻訳できる

  • params.require(:user)ではparamsからキーがuserのバリューのみを受け取る
  • permit(:name, :age)をメソッドチェーンすることによってそのうちnameとageのカラムのみをモデルに受け渡すことを許可している
params.require(:user).permit(:name, :age)

まとめ

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

参考記事

Action Controller の概要 - Railsガイド
permitメソッドを使ってストロングパラメーターにしよう
ストロングパラメータの仕組みを理解しよう!
Rails4 | 新規・変更機能 | マスアサインメント機能と脆弱性とStrong Parameters - Qiita