Railsを学習していると必ずでてくるストロングパラメーター(Strong Parameter)。
技術質問の深掘りとして、AIに下記のように指示を出しました。
Railsのストロングパラメーターについて言語化できるように私に質問して。
この記事では、私がストロングパラメーターについて理解したことと、より深ぼった質問をAIにしてもらったのでその備忘録です。
ストロングパラメーターとは?
ストロングパラメーターは、外部から送られてくる params をそのまま信用せず、Rails が許可したものだけを使うための仕組みです。
不正な値が保存されるのを防ぐために、コントローラーで受け取るパラメーター(ユーザーからのリクエストで送られてくるデータ全て)をチェックし、許可したもの以外は無視します。
これはリクエストの入口で制御すべき責務なので、モデルではなくコントローラーで管理します。
ストロングパラメーターをより深ぼる質問
ストロングパラメーターについてもっと深く理解するため、下記質問をした結果をQ&A形式でまとめました。
意地悪な面接官のたちばで質問してみて
折りたたみ式にしているので、自分で復習するときに使用しようと思います。
Rails学習中の方にもお役に立てば幸いです。
ストロングパラメーターって、結局 permit を書くだけの話ですよね? それを“セキュリティ”って言うのは大げさじゃないですか?
たしかに仕組み自体は permit を書くだけですが、外部入力を一切信用しないという設計思想をコードで強制している点がセキュリティだと思います。
ユーザーが意図的に管理者フラグを送っても、Rails側で「許可したもの意外は絶対に使わないため」、権限昇格を防げます。
params に余計な値が入ってくるって言いますけど、 そもそも画面にない項目って普通送れなくないですか? どうやって送られるんですか?
HTMLフォームにない項目でも、ブラウザの開発者ツールやcurl、Postmanなどを使えば、任意のパラメーターをつけたリクエストを送れます。
Railsはリクエスト内容をそのままparamsにまとめるため、画面にない値もとどきます。
モデルにバリデーションがあるなら、ストロングパラメーターってなくてもよくないですか?
バリデーションはあくまで入力フォームにおくられてくるものが正しいかを判断する物で、モデルよりも前の段階でコントローラーでストロングパラメーターで不正なデータを防ぐ必要があるのではないでしょうか?バリデーションは「データとして正しいか」を判断する仕組みで、そもそも受け取っていいかまでは判断していません。
ストロングパラメーターは、「この項目はアプリとして受け取っていいか」という入り口の制御を担当しているため役割が異なります。
不正なデータを防ぐなら、 モデルで弾いた方が安全じゃないですか? なぜコントローラーなんですか?
ストロングパラメーターは、外部からのリクエストをどう扱うかという問題なので、リクエストを受け取る責務をもつコントローラーで制御します。
モデルはデータの整合性やビジネスルールを担当するため、入り口制御まで行うと責務が重くなります。
じゃあ逆に、 ストロングパラメーターで防げないものって何ですか?
ストロングパラメーターは、「どの項目を受け取るか」は制御できますが、「その値が妥当かどうか」は防げません。
たとえば、emailに不正な形式の値が入ることはバリデーションで防ぐ必要があります。
permit を書き忘れたらどうなります? エラー?保存されない?どっちですか?
permitを書き忘れると、許可されていないパラメーターは除外され、その属性は更新・保存されません。
明示的なエラーはでないため、バグとして気づきにくいのが注意点です。
requireとpermit は、それぞれ何が違って、何を保証してますか?
requireは存在チェック、permitはホワイトリスト制御です。
requireは、必要なキーが存在することを保証します。
permitは、その中で実際に利用していい属性を限定します。
ストロングパラメーターって Rails 独自ですよね? なぜ Rails はこの仕組みを“フレームワーク側で”用意したと思いますか?
開発者が毎回手動でチェックすると書き忘れによる脆弱性が発生しやすいため、Railsはフレームワークとして安全な書き方を強制する仕組みを提供したのだと思います。
セキュリティを個人の注意力に依存させない設計です。
おわりに
この記事は自分が理解するためのアウトプットとして書きました。
同じように、「ストロングパラメーター、なんとなく分かってるけど説明できない」という方の参考になれば嬉しいです。