ゆうべ寝床で思いついた意見。さっそくブログに書こうと、誰か他に言っている人がいないか調べたら、徳丸本の76ページに思いっきり書いてあった。
すなわち、入力値検証の目的は以下の通りです。
- 入力値の間違いを早期に発見して再入力を促すことにより、ユーザビリティ(使いやすさ)を向上する
- 間違った処理を継続することによるデータの不整合などを防ぎ、システムの信頼性を向上させる
もう、これでFAじゃないですか。精読してない俺の馬鹿。
たとえば、ユーザ登録フォームでパスワードが未入力だった場合、アプリケーションは「登録処理に失敗しました」などという曖昧なものではなく「パスワードは必須です」のような明確なメッセージを返すべきだ。それがユーザビリティの向上。
DBにおかしな値が登録されないようにすべきなのは言わずもがな。Railsのドキュメントに「Validations are used to ensure that only valid data is saved into your database.」とある通り。これが信頼性の向上。
ちなみに、このドキュメントには、以下のようにも書かれている。
- Model-level validations are the best way to ensure that only valid data is saved into your database.
- Controller-level validations can be tempting to use, but often become unwieldy and difficult to test and maintain. Whenever possible, it's a good idea to keep your controllers skinny, as it will make your application a pleasure to work with in the long run.
- It's the opinion of the Rails team that model-level validations are the most appropriate in most circumstances.
なので、Railsがコントローラでのバリデーションを推奨するようになったというのはデマです。
入力値のなかには、DBと無関係なものもありうる。「HTML文書のURLを入力するとtitle要素の文字列が返るAPI」を想像すると分かりやすいだろうか。入力値がURL形式であれば、そのURLにアクセスし、ドキュメントをパースするだけ。
こうした、DBと無関係な入力値は、コントローラでバリデーションしてもよいように思える。ただ、少なくともRailsの流儀では、ActiveModel::Modelをインクルードしたモデルでバリデーションするのが普通っぽい。まあ、いずれにしても趣味の問題だろう。
徳丸本の72ページに「文字エンコーディングの妥当性検証を行う理由は、文字コードを使った攻撃手法があるからです」とあるが、ここはしっくりこない。「入力値検証の一部」あるいは「入力値検証の前提」(文字エンコーディングの妥当性を検証しないと、入力値を正しく検証できない)という説明ではダメなんだろうか。
各種インジェクション攻撃やらディレクトリ・トラバーサル攻撃やらについては、それらが起きそうな場所で、文字エンコーディングの妥当性検証を行えばよいわけだし、それほど大変なイメージがいまだに持てないんですよね。しつこくてすみません。