概要
社内でサーバーサイドバリデーションの有用性や必要性などについて議論する機会があった。
そもそもサーバーサイドバリデーションは書くべきなのか書かないべきなのか、何を書くべきなのか
いろいろな視点を想定して自分なりに調べ考えたものをここに書き散らしていく。
なお、前提としてここで言うサーバーバリデーションとは処理前の入力バリデーションのことを指す。
筆者はphp(laravel)環境でこの議論をしているため、動的型付けであることを念頭に置いて読んでいただきたい。
→追記
ご指摘、ご意見をくださった@Zap212さんありがとうございます!
1. サーバーサイドバリデーション不要説
議論の一つとして上がった内容がこれ。
この意見の根拠を簡潔にまとめると
- フロントエンドの実装にほぼ同じ内容のバリデーションを書くから(悪意のあるユーザーやバグによる想定外のリクエスト以外はフロント側で処理できる)
- サーバーバリデーションは普通デフォルトではエラーログを吐かないので、クライアント側でサーバー側バリデーションのエラーをキャッチしていない時に
クライアント側で予期していない動作が起こる可能性がある - クライアントでも書いているバリデーションロジックをサーバーサイドでも書くことによる単純な工数増加(工数増加に見合ったリターンが少ないと考える)
- サーバーバリデーションを書いたから必ず期待しているリクエストが受け取れるわけではない
- 想定外の型のデータが来たとしてもバグが出れば422エラーと違いサーバーログで捕捉できるからデバッグしやすい
2. サーバーサイドバリデーション必要説
->サーバーサイドバリデーション不要説に対する異論やデメリット、リスクを上げていく
フロントエンドの実装にほぼ同じ内容のバリデーションを書くから(悪意のあるユーザーやバグによる想定外のリクエスト以外はフロント側で処理できる)
フロントエンドのバリデーションに不足があった際に想定外の動作を引き起こす可能性はかなり高くなる
→処理側はリクエストの型や形式が一定のルールのものを期待している。
そこに制限がなければ期待していない動作を起こす可能性は非常に高い
ex) boolを期待しているパラメータにstringが来る、動的型付けだと空文字以外がtrueとみなされ、クライアントが期待しているリクエストと全く違うリクエストとして受け取られてしまう、など
サーバーバリデーションは普通デフォルトではエラーログを吐かないので、クライアント側でサーバー側バリデーションのエラーをキャッチしていない時に
クライアント側で予期していない動作が起こる可能性がある
そもそもクライアント側でエラーハンドリングは書く前提であるべきである。書かない場合は429や500など比較的発生しうる問題にも対応できないため非常に不安定なアプリケーションとなってしまう
クライアントでも書いているバリデーションロジックをサーバーサイドでも書くことによる単純な工数増加(工数増加に見合ったリターンが少ないと考える)
サーバーサイドバリデーションを書かないことにより、実装の抜けが表面化せずリリース後など運用段階で表面化した際にかかる修正工数やサービスの信用等を考慮するならば書くべきではないか
(型を制限できないので全てのパラメータと型の組み合わせに対して処理を書く必要があり、無駄が多い。)
サーバーバリデーションを書いたから必ず期待しているリクエストが受け取れるわけではない
laravel環境においてはFormRequestクラスからインスタンス関数のvalidated()メソッドを使うことによってバリデーションを通過したパラメータのみを含めた配列を取得することが可能。書かない場合は完全に実装側のセキュリティモラルに任せるしかない(複数代入・SQLインジェクション・...etc)
ホワイトリストでリクエストを受け取ることにより、意図していないリクエストをカットしつつ、おおよそ期待しているリクエストだけを取得することができる
想定外の型のデータが来たとしてもバグが出れば422エラーと違いサーバーログで捕捉できるからデバッグしやすい
トランザクション処理にしてなかったり、外部サービス依存の処理だったり、などエラーの捕捉と処理のロールバックができる設計ができていない場合、ログでバグの内容は捕捉できるが想定外の処理結果が残ってしまう。(バリデーションエラーもログ出力そのものは可能)
結論
サーバーバリデーションは可能な限りセキュリティリスクを減らすために必須なものと考える。開発者のセキュリティモラルやテストの品質の高さである程度回避できるものはあるが、書かないことによる潜在的リスクの方が怖いのでとりあえず書いとけ派ではある。
→追記
フロントか、バックエンドのどちらかに書くのであればバックエンドに書いてバックエンド側からのバリデーションエラーレスポンスをフロント側で処理する方が良い
(フロントで書くよりサーバーとの通信の分少々遅くなるがセキュリティリスクは低減できる)
参考にさせて頂いた記事
語彙力のない自分でもわかる範囲で言語化しただけで書いてあることは以下の記事の方がしっかりしているし詳細に理解できるのでこちらを読むことをお勧めする。
最後に
- 普段なんで書くのかなどあまり考慮せず書くべきものだと思って書いていたが、改めてなぜ書くのか意味を明確にできていい機会になった。
- 今回、可能な範囲で様々な視点で考察してみたが、所詮一個人の一意見でしかないので、こういった考えの奴もいるんだな、程度で考えて欲しい。
- どの立場で考えるかによって何が正義か変わるので一概には決め難い点もある。(工数/納期/工賃/チームの開発力/開発者のセキュリティモラル/...etc)