質問: rails初学者です。 ストロングパラメータについて学んでいたのですが、課題として作ったアプリケーションにおいて、一部カラムでストロングパラメータを使わなくてもDBへの登録ができてしまうのが腑に落ちず、理解があっているのか質問させてください。 件のコードは以下のような感じです。 ``` test.rb Class TestController < ApplicationController ・・・中略 #フォームから入力されたデータをTestモデルに登録するメソッド #その際、test_paramsメソッドを呼び出す def create Test.create(image: test_params[:image], text: test_params[:text],user_id: current_user) end ・・・中略 #createメソッドから呼び出され、引数となっている値がストロングパラメータとして設定されているか検証 #falseとした場合は、DBへの登録を制限する private def test_params params.permit(:image, :text) end ``` ### 【質問内容】 **1以下の理解であっているでしょうか。** ストロングパラメータ自体がViewから引き渡されたparams内に定義されたカラムを検証対象としている。 そのため、params[:XXXX]を直接createで指定するとストロングパラメータ不使用でエラーとなる。 ただし、paramsを使わずに設定した値(上の例だと"user_id:")は、ストロングパラメータの包囲網には引っかからず、普通に登録できてしまう。 **2どうするのがベターなのか。** ユーザからリクエストを受けるデータは全てparamsに格納されるので基本的にセキュリティ的な問題は無いという理解ですが、個人的には、current_user自体もセッション情報だと思うので、ユーザ入力情報と同義なのではと・・・。 ただ、”なりすましによる改ざん”と今回のストロングパラメータで回避しようとしている事象は違うので気にしなくて良いと言う結論なのでしょうか・・・とか、纏まらず、うやうや考えています。 そのため、書き方として、どちらがいいのか、ご意見をください!!! また、どちらも使う場合、利用ケースを教えてくださると嬉しいです!!!! **1.params指定以外の設定値は、ストロングパラメータを経由しない** 例)今回の参考コードと同一 **2.params指定以外の設定値も、ストロングパラメータ検証用のメソッドを経由する** 例)以下のようにストロングパラメータの検証用メソッドに値をマージする ``` test.rb Class TestController < ApplicationController ・・・中略 #フォームから入力されたデータをTestモデルに登録するメソッド #その際、test_paramsメソッドを呼び出す def create Test.create(test_params) end ・・・中略 #createメソッドから呼び出され、引数となっている値がストロングパラメータとして設定されているか検証 #falseとした場合は、DBへの登録を制限する private def test_params params.permit(:image, :text).merge(user_id: current_user.id) end ``` ※初心者課題のため、モデル更新にもform_tagを利用しています。 そのため、paramsメソッドに続く'require'メソッドの記述がありませんが、これは意図したものです。 初心者につき、明後日な質問をしているかもしれません。 長文・蛇文となり、申し訳ございませが、ご教示何卒よろしくお願いいたします。
回答: まず、Strong Parameterが何のためにあるのかといえば、**Mass Assignment脆弱性**を防ぐため(`params[:user]`とそのまま投げ込んで、意図しない列まで書き換わるという問題への対策)です。なので、1列ごとにピックアップするのであればStrong Parameterに頼らなくても全く問題ありません。 > > 1以下の理解であっているでしょうか。 > > > はい、大筋では間違いありません。 > > 2どうするのがベターなのか。 > > > 「一部の列しか書き換えない」という意図を、Strong Parameterで表現するか、各列を明示的に宣言して表現するかの問題なので、元のコードの書き方で構いません(下手に`params`に`merge`してしまうと、`merge`したものが`permit`されていないとみなされて、うまく動きません)。