検証はどこで行うのですか?モデル、コントローラー、またはビュー
-
02-07-2019 - |
質問
Web フォーム アプリケーションのどこにユーザー入力検証を配置しますか?
- ビュー:JavaScript クライアント側
- コントローラ:サーバー側言語 (C#...)
- モデル:データベース (ストアド プロシージャまたは依存関係)
各レベルで必要な検証があると思います。
- ユーザーは正しい値を入力しましたか
- 日付は実際の日付、数値は実際の数値です...
- 1.のチェックをすべて行います。再度、悪意のある攻撃 (IE XSS または SQL インジェクション) をチェックします。
- 1.で行ったチェック。これは主に、ユーザーが間違いを犯した場合にサーバーの往復を回避するためのものです。
- これらは JavaScript のクライアント側で実行されるため、実行されたかどうかを信頼することはできません。これらの値を再度検証すると、一部の悪意のある攻撃が阻止されます。
- 依存関係は満たされていますか (つまり、ユーザーは有効な質問にコメントを追加しましたか)
- 優れたインターフェースにより、これらを侵害することが非常に困難になります。ここで何かが引っかかった場合は、何か非常に問題が発生したことになります。
[に触発された この返答]
解決
私はすべての層をチェックインしますが、私が使用している検証テクニックを書き留めておきたいと思います。
データベース層で検証します。モデルに適切な制約を設定すると、データ整合性が自動的に検証されます。
これは、ほとんどの Web プログラマーにとって忘れられている技術です。
他のヒント
モデル内の検証。モデルからヒントを取得してユーザー エクスペリエンスを向上させる、UI 内の自動ルーチン (オプション)。
自動化されたルーチンとは、ユーザー インターフェイスにモデルごとの検証コードが存在すべきではないことを意味します。RoR などの検証メソッドのライブラリ ( validates_presence_of :username などのメソッドがある) がある場合、コントローラーまたはビューはこれらを読み取り、同等の JavaScript (または便利なものなら何でも) メソッドを適用できる必要があります。
つまり、UI で完全な検証ライブラリを複製するか、既存のものを使用する場合は少なくともマッピングを提供する必要があります。ただし、それが完了すると、モデルの外部に検証ロジックを記述する必要はなくなります。
検証はすべてのレイヤーで実行できます。
Web フォームからの入力 (すべての文字列、適切な型へのキャストなど) の検証は、Web サービスや XML ファイルなどからの入力の検証とは異なります。それぞれに独自の特殊なケースがあります。もちろん、Validator ヘルパー クラスを作成して、Validation を外部化し、ビューで共有できるようにすることもできます。
次に、DAO レイヤーの検証を行います。モデル内に永続化するのに十分なデータがあるか (NULL 制約を満たすためなど)、などです。データベースにチェック制約を設定することもできます (ステータスは ('N'、'A'、'S'、'D') などです)。
これは面白い。長い間、私はモデル内のすべての検証を、DAL (データ アクセス層) と考えられるもののすぐ上で実行していました。私のモデルは通常、抽象化と低レベル API を提供する DAL を備えたテーブル データ ゲートウェイに従ってパターン化されています。
TDG 内で、次のようなビジネス ロジックと検証を実装します。
- ユーザー名が空ですか
- ユーザー名は 30 文字以上です
- レコードが存在しない場合はエラーを返す
アプリケーションが複雑になるにつれて、検証の多くは JavaScript を使用してクライアント側で実行できることに気づき始めました。そこで、検証ロジックのほとんどを JS にリファクタリングし、モデルをクリーンアップしました。
その後、サーバー側の検証 (フィルタリング/エスケープではなく、これは異なると考えています) はおそらくサーバーでも行われ、おまけとしてクライアント側でのみ実行されるべきであることに気づきました。
そこで、INPUT 検証/アサーションとビジネス ルール/ロジックの間には明確な違いがある可能性があることに再度気づいたとき、検証ロジックは元に戻りました。
基本的に、アプリケーションのクライアント側で(JSを使用して)実行できる場合、これはINPUT検証であると考えます...モデルによって実行する必要がある場合(このレコードはすでに存在しますか?など)、それを考慮しますビジネスの論理。混乱を招くのは、両方ともデータ モデルの整合性を保護することです。
ユーザー名の長さを検証しない場合、ユーザーが 1 文字のユーザー名を作成するのを防ぐにはどうすればよいでしょうか?
そのロジックを次にどこに配置するかはまだ完全に決まっていません。それは、薄いコントローラー、重いモデル、あるいはその逆など、どちらを優先するかによって決まると思います...
私の場合、コントローラーははるかにアプリケーション中心である傾向がありますが、モデルは慎重に作成すれば、内部だけでなく「他の」プロジェクトでも再利用できることが多いため、モデルを軽量にし、コントローラーをより重い側に保つことを好みます。
あなたをどちらかの方向に動かす力は、実際には個人的な意見、要件、経験などです...
興味深いテーマです:)
検証 しなければならない コントローラ内で行われます。安全性と応答性が保証されるのはコントローラだけです。
検証 すべき ビュー内で行われます。これが連絡先となり、最適な UE が提供され、サーバーの余分な作業が節約されます。
検証 意思 ただし、特定のコアレベルのチェックのみが対象です。データベースは常に適切な制約を反映する必要がありますが、これを実際の検証に使用するのは非効率です。また、データベースが単純な制約で有効な入力を判断できるとは限りません。
すべての検証は少なくとも 1 回実行する必要があり、これは値オブジェクト (DTO と混同しないように DDD の意味で) 内であっても、エンティティ自体のビジネス オブジェクトを通じてであっても、中間層で行う必要があります。ユーザーエクスペリエンスを向上させるために、クライアント側の検証を行うことができます。私は、フォーム上で間違っている点をすべて一度に公開できるため、クライアント側の検証は行わない傾向があります。ただし、それは私の個人的な好みにすぎません。ロジックを間違えた場合に備えて、データの整合性を保証するためにデータベースの検証が行われることがあります。中間層またはバックエンドの何か。
私はビューとコントローラーでのみこれを行います。データベースはデータ型などによってその一部を強制しますが、エラーをキャッチせずにそこまで到達しないことを望みます。
ただし、あなたは自分の質問にほぼ答えていますが、知っておくべき重要なことは、ビューを決して信頼できないということです。ただし、それがユーザーにフィードバックを提供する最も簡単な方法であるため、少なくとももう 1 つのレベルでサニタイズする必要があります。
うーん、よくわかりません。この記事を読むまではコントローラーと言っていたでしょう。細いコントローラー、太いモデル
ほとんどの検証は以下に依存するため、 ビジネスルール, で検証を行います。 ビジネス層 サードパーティのツールクラスとして。ユーザー入力など、他のタイプの検証もあり、コントローラーで行う必要がありますが、これらの検証ルールをサードパーティのクラスでカプセル化することもできます。実際のところ、それは何を検証するかによって異なります。
クライアント側の検証は軽微な検証であり、軽量の検証を構築するために作成されたものです。 入力検証, ただし、サーバー側の検証は 常に必要. 。ユーザー入力を決して信頼することはできません ;)
。ネット 検証を構築するための優れたコントロールがありますが、 ビジネス層 データを検証するには常により良いアプローチが必要ですが、それらのコントロールではそのタスクには十分ではありません。
ビューでの簡単な入力検証。モデル内の完全な検証。理由?ビュー テクノロジを変更し、検証がビュー/コントローラー内にある場合は、新しいビュー用に検証を書き直す必要があります。これによりバグが発生する可能性があります。これをモデルに配置すると、すべてのビューで再利用されます。
ただし、先ほども述べたように、速度と容易性を考慮した単純な検証です。